2

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

Jack James
  • 5,252
  • 6
  • 36
  • 38
  • Call your "Done" method in the callback of the ajax request, and have the "Done" method only do anything when all the records have been retrieved (given that you know how many records you are expecting). – Mansfield May 09 '13 at 16:38

2 Answers2

4

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")
});
Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

$.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.

GNi33
  • 4,459
  • 2
  • 31
  • 44
  • Although I didn't show it in my example, the callback is already getting used. My issue was that the getJSON instruction is called multiple times, and I only want to know when the _last_ one is run. – Jack James May 10 '13 at 08:43