jQuery callback for multiple ajax calls
Looks like you've got some answers to this, however I think there is something worth mentioning here that will greatly simplify your code. jQuery introduced the $.when
in v1.5. It looks like:
$.when($.ajax(...), $.ajax(...)).then(function (resp1, resp2) { //this callback will be fired once all ajax calls have finished.});
Didn't see it mentioned here, hope it helps.
Here is a callback object I wrote where you can either set a single callback to fire once all complete or let each have their own callback and fire them all once all complete:
NOTICE
Since jQuery 1.5+ you can use the deferred method as described in another answer:
$.when($.ajax(), [...]).then(function(results){},[...]);
for jQuery < 1.5 the following will work or if you need to have your ajax calls fired at unknown times as shown here with two buttons: fired after both buttons are clicked
[usage]
for single callback once complete: Working Example
// initialize herevar requestCallback = new MyRequestsCompleted({ numRequest: 3, singleCallback: function(){ alert( "I'm the callback"); }});//usage in request$.ajax({ url: '/echo/html/', success: function(data) { requestCallback.requestComplete(true); }});$.ajax({ url: '/echo/html/', success: function(data) { requestCallback.requestComplete(true); }});$.ajax({ url: '/echo/html/', success: function(data) { requestCallback.requestComplete(true); }});
each having their own callback when all complete: Working Example
//initialize var requestCallback = new MyRequestsCompleted({ numRequest: 3});//usage in request$.ajax({ url: '/echo/html/', success: function(data) { requestCallback.addCallbackToQueue(true, function() { alert('Im the first callback'); }); }});$.ajax({ url: '/echo/html/', success: function(data) { requestCallback.addCallbackToQueue(true, function() { alert('Im the second callback'); }); }});$.ajax({ url: '/echo/html/', success: function(data) { requestCallback.addCallbackToQueue(true, function() { alert('Im the third callback'); }); }});
[The Code]
var MyRequestsCompleted = (function() { var numRequestToComplete, requestsCompleted, callBacks, singleCallBack; return function(options) { if (!options) options = {}; numRequestToComplete = options.numRequest || 0; requestsCompleted = options.requestsCompleted || 0; callBacks = []; var fireCallbacks = function() { alert("we're all complete"); for (var i = 0; i < callBacks.length; i++) callBacks[i](); }; if (options.singleCallback) callBacks.push(options.singleCallback); this.addCallbackToQueue = function(isComplete, callback) { if (isComplete) requestsCompleted++; if (callback) callBacks.push(callback); if (requestsCompleted == numRequestToComplete) fireCallbacks(); }; this.requestComplete = function(isComplete) { if (isComplete) requestsCompleted++; if (requestsCompleted == numRequestToComplete) fireCallbacks(); }; this.setCallback = function(callback) { callBacks.push(callBack); }; };})();
Not seeing the need for any object malarky myself. Simple have a variable which is an integer. When you start a request, increment the number. When one completes, decrement it. When it's zero, there are no requests in progress, so you're done.
$('#button').click(function() { var inProgress = 0; function handleBefore() { inProgress++; }; function handleComplete() { if (!--inProgress) { // do what's in here when all requests have completed. } }; $.ajax({ beforeSend: handleBefore, complete: function () { // whatever handleComplete(); // whatever } }); $.ajax({ beforeSend: handleBefore, complete: function () { // whatever handleComplete(); // whatever } }); $.ajax({ beforeSend: handleBefore, complete: function () { // whatever handleComplete(); // whatever } });});