0

I have an ajax call that retrieves data and on the success of it, runs a loop and runs functions that run more ajax calls.

CODE:

success: function(data){
                // FIRST MAKE SURE DATA WAS FOUND
                console.log(data);
                if(data["status"] == "found")
                {
                    // CREATE NEEDED ARRAY FROM SINGLE STRING
                    var restrictionArray = data["data_retrieved"].split(',');

                    loop_amount = restrictionArray.length; //<!-- AMOUNT TO BE LOOPED FOR BUILDING FORMS
                    //var Action = this.Elevation.getActionsByOptionId(Option.getID())[i];
                    for(var j = 0; j < loop_amount; j++)
                    {
                        var EditRowRestriction = OptionRules.prototype.getEditRowRestriction(j);
                        var check = $(EditRowRestriction).find("select");

                        console.log(check[0]);

                        var EditRowRestirction_select_ability = OptionRules.prototype.getEditRowRestriction_select_ability(j);
                        //var EditRowRestirction_access_ability = OptionRules.prototype.getEditRowRestriction_access_ability(j);

                        EditRowRestriction.onremove = function()
                        {
                            $(this).next().empty(); <!-- RESTRICTION SELECT ABILITY REMOVE
                            //$(this).next().next().empty(); <!-- RESTRICTION ACCESS ABILITY REMOVE
                            $(this).empty();

                            //var Action = this.Action;
                            //that.removeAction(Action);
                        }
                        tbody.appendChild(EditRowRestriction);
                        tbody.appendChild(EditRowRestirction_select_ability);
                        console.log(check[1]);
                    }
                }
            },
            error:function(){
                alert("An error occured, please try again.");
            }

Heres the problem, inside the for loop; those methods link to another method that invokes an ajax call. What happens here is even before the ajax call's finish, the loop is always continuing and those methods are always being called. What I want to do is to stop the loop until those methods have returned based on the ajax call's being finished. And than to invoke the last 2 lines of code within the loop:

tbody.appendChild(EditRowRestriction);
tbody.appendChild(EditRowRestirction_select_ability);

What would be my best approach to accomplishing this?

Suggestions, thoughts?

David Biga
  • 177
  • 13
  • Best case would be to consolidate all of these looping ajax requests to a single method that does all of this looping etc server-side, however, if that isn't an option, what you need is to send each request, one by one, after the completion of the previous request. This can be done using `.then` – Kevin B Jun 02 '14 at 17:50
  • @KevinB is there a quicker fix to just somehow listen to the method and wait for the proceeding `ajax` call to finish and than continue? – David Biga Jun 02 '14 at 17:51
  • No, there isn't. you can't pause a loop. – Kevin B Jun 02 '14 at 17:52
  • So. What about returning after an ajax call is finished. I know that when trying to do that the function above it is already running through whether it gets that returned value right away but is there a way to make it wait for something' to be returned? – David Biga Jun 02 '14 at 17:53
  • Nope, by the time any return would happen, the parent function will have already stopped executing. – Kevin B Jun 02 '14 at 17:53
  • Okay I see, so you recommend using a `.then`? – David Biga Jun 02 '14 at 17:54
  • I recommend doing the looping serverside, but if that isn't an option, then yes, .then would be appropriate – Kevin B Jun 02 '14 at 17:55
  • @KevinB Actually dgvid works perfectly – David Biga Jun 02 '14 at 18:02
  • 1
    That is an absolutely terrible way of solving this problem. – Kevin B Jun 02 '14 at 18:05
  • For example, say you are looping 5 times on the outer loop, and then 10 times on the inner loop. That's 50 ajax requests total. If each ajax request takes 50ms to complete, thats 2 and a half seconds of the user being unable to interact with the browser, no loading spinners will spin, etc. If you instead used asynchronous ajax, you could perform 3-5 requests simultaneously, potentially reducing the required time to 1 second or less pending on how many simultaneous requests your browser/server supports, while also not causing the user to be unable to interact with the browser. – Kevin B Jun 02 '14 at 18:15

2 Answers2

1

It would be best to consolidate all of this looping with a single server-side script, however, if that isn't an option, you can use .then:

var def = $.Deferred(function(def){
    def.resolve();
}).promise(); // used to start .then chain

for (var i = 0; i < 10; i++) {
    def = def.then(function () {
        return $.ajax({});
    });
}
def.done(function(){
    // All requests from chain are done
    console.log('all done');
});

http://jsfiddle.net/kg45U/

Kevin B
  • 94,570
  • 16
  • 163
  • 180
-1

You could modify the calls to $.ajax within the loop to execute synchronously, rather than asynchronously. (See SO question How can I get jQuery to perform a synchronous, rather than asynchronous, AJAX request?.) This would have the effect of "pausing" the loop while the inner ajax calls execute. This would be the most straightforward approach, but does have the disadvantage of locking up the user's browser while those ajax requests execute.

The alternative is to break up the code with the loops into pieces, so that you complete the processing with the loop in a callback function that is invoked after the inner-ajax calls have completed.

Community
  • 1
  • 1
dgvid
  • 26,293
  • 5
  • 40
  • 57