Don
Don

Reputation: 497

Wait for AJAX to finish before proceeding with the loop?

Why is it that whenever I put an ajax inside a for loop, it doesn't synchronize well?

like for example, my code is:

    function addToUserGroupList() {
        _root.qDomId('js-assignGroupArrBtn').disabled = true

        for (var i = 0; i < selectedIds.length; i++) {
            $.ajax({
                type: "POST",
                url: 'groupManage.ashx',
                dataType: 'text',
                data: 'type=getInfo&groupId=' + selectedIds[i],
                success: function (result) {
                    if (result != '') {
                        this.groupName = result.split('&')[0];
                        this.groupNotes = result.split('&')[2];

                        userGroupList.push({ 'uid': parseInt(selectedIds[i]),
                            'name': this.groupName,
                            'adminStr': this.groupNotes
                        });

                        _root.userListObj.gourpInst.gourpTB(userGroupList);
                    }
                },
                error: function (XMLHttpRequest, status, errorThrown) {
                    alert('failed to add to user\'s group.');
                }
            });
        }

        _root.qDomId('js-assignGroupArrBtn').disabled = false;
        selectedIds = [];
    }

Why is that it calls out selectedIds = []; first before the Ajax Query? Is it possible to let the ajax queries be finished before proceding to selectedIds = [];? Because it clears the array right before it's finished doing the stuffs. :/

Upvotes: 1

Views: 3483

Answers (1)

jfriend00
jfriend00

Reputation: 707328

First off, you really need to understand how an Ajax call is Asynchronous (that's what the "A" in Ajax stands for). That means that calling $.ajax() only starts the ajax call (it sends the request to the server) and the rest of your code happily continues running. Sometimes LATER after the rest of your code has executed, the success or error callback handler is called when the response comes back from the server. This is NOT sequential programming and must be approached differently.

The #1 thing this means is that ANYTHING that you want to have happen after the ajax call MUST be in the success or error handler or called from there. Code located right after the ajax call will be run long before the ajax call completes.


So, there are different ways to structure your code to work with this asynchronous concept. If you only want one asynchronous ajax call in flight at a time, you have to do this restructuring and can't use a simple for loop. Instead, you can create an index variable and in the completion function, increment the index and kick off the next iteration. Here's one way to code it:

function addToUserGroupList() {
    _root.qDomId('js-assignGroupArrBtn').disabled = true

    var i = 0;
    function next() {
        if (i < selectIds.length) {
            $.ajax({
                type: "POST",
                url: 'groupManage.ashx',
                dataType: 'text',
                data: 'type=getInfo&groupId=' + selectedIds[i],
                success: function (result) {
                    i++;
                    if (result != '') {
                        this.groupName = result.split('&')[0];
                        this.groupNotes = result.split('&')[2];

                        userGroupList.push({ 'uid': parseInt(selectedIds[i]),
                            'name': this.groupName,
                            'adminStr': this.groupNotes
                        });

                        _root.userListObj.gourpInst.gourpTB(userGroupList);
                    }
                    next();
                },
                error: function (XMLHttpRequest, status, errorThrown) {
                    alert('failed to add to user\'s group.');
                }
            });
        } else {
            // last one done
            _root.qDomId('js-assignGroupArrBtn').disabled = false;
            selectedIds = [];
        }
    }
    // kick off the first one
    next();
}

Upvotes: 6

Related Questions