Jack James
Jack James

Reputation: 5372

How do I trigger something only when batch of getJSON instructions completes?

Here's some of my code:

for (var i = 0; i < recordList.length; i++) {
  var recordID = recordList[i];
  populateDataRow(i, recordID, columns) 
};
console.log("done");

Here populateDataRow is a function that uses $.getJSON The problem is (in Google Chrome at least), the console.log statement is triggered long before the populateDataRow cycles are completed

Upvotes: 2

Views: 960

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074168

Yes, the console.log happens first because getJSON is asynchronous. Your code starts it, but it finishes later, after the subsequent code runs.

To handle that, you'll need to use the "completion" callback on getJSON. Your code above would remember how many calls it's started, and wait for that many completions before continuing.

You can also have your populateDataRow function return the return value of getJSON, save up those objects, and then use jQuery.when to get a notification when they've all finished.

Here's an example: Live Copy | Live Source

var deferreds = [],
    index;

for (index = 0; index < 4; ++index) {
  deferreds.push($.getJSON("http://jsbin.com/agidot/1", function() {
    display("One finished");
  }));
}
$.when.apply($, deferreds).then(function() {
  display("All finished")
});

function display(msg) {
  $("<p>").html(String(msg)).appendTo(document.body);
}

Note that we only see "All finished" when all four calls have finished.

The call to $.when is a bit of a hassle. For some reason, you can't just pass an array of Deferred objects into it. So I used Function#apply to call it and pass each entry of the array as a discrete argument.


I was surprised that $.when doesn't accept an array and handle that usefully, but I see other answers here also saying to use apply: Here and Here.

If you were going to use arrays a lot, I think I'd probably have this in my standard toolkit of jQuery extensions:

(function($) {
    $.whenAll = function(deferreds) {
        return $.when.apply($, deferreds);
    };
})(jQuery);

...and then the end of the code example above would be:

$.whenAll(deferreds).then(function() {
  display("All finished")
});

Upvotes: 4

GNi33
GNi33

Reputation: 4509

$.getJSON is a shorthand-function for jQuery's $.ajax()-function. An XHR (or AJAX) - call is asynchronous, your other code will be executed further, you'll need to provide a callback-function that is executed when the AJAX-call is completed.

From the API (http://api.jquery.com/jQuery.getJSON/)

$.getJSON('ajax/test.json', function(data) {

});

Here, function(data){} is the callback-function, provided as argument to getJSON. If you want to do something with the returned data, you'll need to do it in this function or after this function has been executed.

Upvotes: 0

Related Questions