4

I have a circumstance where I need to make several getJSON calls, and once all of the data is returned make a call to another function, like so (code simplified for example):

var data = {};
for (var i in a) {
    $.getJSON(base_url+i, function(d) {
        data[i] = d;
    });
}
do_something(data);

Obviously this doesn't work as I am making the call to do_something before the getJSON calls have returned any data.

My current approach to get around this is to make the calls synchronously, like so:

var data = {};
$.ajaxSetup({'async':false});
for (var i in funcs) {
    $.getJSON(base_url+i, function(d) {
        data[i] = d;
    });
}
$.ajaxSetup({'async':true});
do_something(data);

My question is, is there a better way of doing this or am I best off making the calls synchronously as above?

Mitch Satchwell
  • 4,770
  • 2
  • 24
  • 31
  • 1
    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 Aug 10 '12 at 10:05
  • The better solution is to use deferred objects. Have a look at the answers in the linked question. There are also many related questions: http://stackoverflow.com/search?q=jquery+ajax+wait+for+multiple+requests – Felix Kling Aug 10 '12 at 10:11
  • @FelixKling I didn't see that question while doing a search, it sounds like deferred objects might be what I am looking for. I will give that a go, thanks. – Mitch Satchwell Aug 10 '12 at 10:11

2 Answers2

6

As per link posted by Felix Kling to a similar question, the answer was to use deferred objects.

However, there is a further complication due to the use of i in the getJSON success function. This would always be the value of the last iteration. See my other question for more details: jQuery Deferred - Variable scope in deferred getJSON success functions

Full solution:

var data = {};
var calls = [];
for (var i in funcs) {
    calls.push(
        $.getJSON(base_url+i,
            (function(i) {
                return function(d) {
                    data[i] = d;
                };
            }(i)) 
        )
    );
}
$.when.apply($,calls).then(function() {
    do_something(data);
});
Community
  • 1
  • 1
Mitch Satchwell
  • 4,770
  • 2
  • 24
  • 31
  • I was wondering if there is a way to stop the for loop if var d has a specific value? Example if d > 0 then the loop should stop. Is this possible? – Panos May 01 '21 at 15:21
0

I had the same problem with a recent application I was developing.

In this case the best option to handle the data and be sure that your function is being executed when you really have got it is to put the functions inside the $.getJSON call.

In your case it would look like this:

var data = {};
for (var i in funcs) {
    $.getJSON(base_url+funcs[i], function(d) {
        data[f] = d;
        do_something(data);
    });
}

Like this you will be sure that the call will be done when the data is handled and this doesn't give errors.

Nuxy
  • 386
  • 1
  • 2
  • 17
  • 1
    But this executes the function for each Ajax request, not once after all of them completed. – Felix Kling Aug 10 '12 at 10:09
  • Wouldn't work in my case as I need to call the function after all of the json calls have returned, not after each one. – Mitch Satchwell Aug 10 '12 at 10:09
  • oh, that's true, I missunderstood that part. In my case it was at each json call. So in that case check @Felix Kling url. – Nuxy Aug 10 '12 at 10:10