1

I'm experiencing the following problem.

I have the following nested / foreach loops ajax call structure:

var children = [];
$.fn.ajaxHelper.loadAjax({
    url: someUrlReturningJsonOfChildren,
    cache: true,
    callback: function(options) {
        var json = options.json;
        $.each(json, function (i) {
            // get the details of this child
            $.fn.ajaxHelper.loadAjax({
                url: urlForDetailsUsingId,
                cache: true,
                callback: function(options) {
                    var json = options.json;
                    children[i] = json;   
                }
            });
        }
    }
});
// want to do something with (newly filled) children here

As you can imagine, I'm running into the trouble that the ajax calls are asynchronous (duh), but I want to do something with the children array only when all the ajax calls are done. Otherwise I'm obviously dealing with an incomplete array.

I have been looking at some jQuery solutions such as Deferred objects (using $.when().then() and such), but that would only solve the problem if I would not have the foreach-loop (as far as I can tell).

Also, changing the REST API (where the ajax calls are going) is not an option unfortunately, due to specified requirements regarding the API.

Ok, so without further ado: can anyone of you geniuses help me with this? :-)

bknopper
  • 1,193
  • 12
  • 28
  • 2
    Using `$.when` would solve the problem. You have to create an array of promises and call $.when with .apply. This has already been covered a couple of times here. – Felix Kling Mar 06 '14 at 16:40
  • 2
    possible duplicate of [Multiple ajax calls inside a each() function.. then do something once ALL of them are finished?](http://stackoverflow.com/questions/8726046/multiple-ajax-calls-inside-a-each-function-then-do-something-once-all-of-the) – Felix Kling Mar 06 '14 at 16:44
  • @FelixKling - you are correct, this is a duplicate; furthermore, I like your answer better then mine (below). – losthorse Mar 06 '14 at 19:36
  • I agree with @FelixKling. And I am of a mind to close this question (because of duplication and the answers on that question). Hate to throw away the discussions though, but can't accept an answer really either (because of the better answer in the question I (unfortunately) duplicated. Anyone thoughts on possible solutions? – bknopper Mar 07 '14 at 08:27

3 Answers3

2

ajax is asynchronous by default but you can turn it off. Here goes the API on how to do it

https://api.jquery.com/jQuery.ajax/

heres a little demp

$.ajax({
   url: my_url.php,
   type: "POST",
   async: false,
   dataType: 'json'
});

Or just make your next ajax call in a success function (Recommended)

function testAjax(handleData) {
   $.ajax({
   url:"getvalue.php",  

   success:function(data) {
      //next ajax call here
   }

 });
}
MGot90
  • 2,422
  • 4
  • 15
  • 31
  • Please thumbs up if you like the answer :) – MGot90 Mar 06 '14 at 16:44
  • I guess the question the OP might have is how to convert the loop to this pattern. Also this will make the Ajax calls sequential, not parallel, so it might take longer until all the results are received. – Felix Kling Mar 06 '14 at 17:49
0

You must run ajax query when previous query is completed with success (in jQuery onSuccess callback)

LONGMAN
  • 980
  • 1
  • 14
  • 24
0

I had a smiler issue... below is a simplified version of my solution.

Step one: Declare global variables.

var results1,
    results2,
    [resultsN];

Step two: Make a function that accepts the results of each AJAX call as parameters.

function foo(results1, results2, [resultsN]) {
    if (results1, results2, [resultsN]) {
        //... do whatever you want with all of your results
    }
}

Step three: Call all of the AJAX functions, set results to global variables, and call function foo for each.

function ajax() {
    //AJAX call 1
    $.ajax({
        type: 'POST',
        url: //URL,
        success: function (data, textStatus, jqXHR) {
            results1 = data;
        },
        dataType: 'json',
        complete: function () {
            foo(results1, results2);
        }
    });

    //AJAX call 2
    $.ajax({
        type: 'POST',
        url: //URL,
        success: function (data, textStatus, jqXHR) {
            results2 = data;
        },
        dataType: 'json',
        complete: function () {
            foo(results1, results2);
        }
    });
};

This method has the advantage of running as fast as the longest AJAX call takes. If you simply nest AJAX queries in the complete event then you will have to wait for each AJAX call to complete before moving to the next one...

losthorse
  • 1,530
  • 1
  • 13
  • 33
  • I would advice against using n global variables and use an array instead. – Felix Kling Mar 06 '14 at 17:47
  • @FelixKling - I agree. I use object oriented JavaScript and set this variable to a property instead. You could use an array to reduce the number of global variables but I did not want to muddy the water in this example. – losthorse Mar 06 '14 at 19:27