Function call after all ajax requests are executed when using foreach statement in jQuery

I have each statement and inside it I call ajax to send some information to the server.

 $.each(array, function(k, v) { $.ajax({ ... }); }); 

When all ajax requests are executed, the function is called here ... How to do this?

I cannot use the async: false flag anymore because it is deprecated.

+5
source share
1 answer

Store the promises returned by $.ajax in an array, and then use $.when to wait for them to complete:

 var promises = []; $.each(array, function(k, v) { promises.push($.ajax({ ... })); }); $.when.apply($, promises).then(function() { // They're all done now }); 

or using $.map :

 $.when.apply($, $.map(array, function(k, v) { return $.ajax({ ... }); })).then(function() { // They're all done now }); 

You want to look at done , then and always to determine what works best for your scenario.

$.when API is a broken bit , intended for a slightly different use case, so we should call it an odd way. What he does is take a bunch of promises as discrete arguments and return a new promise that will be resolved when all the promises you pass are resolved. For instance:.

 $.when(promise1, promise2, promise3).then(...); 

But often we have an array of promises (for example, in the above). Since it expects discrete arguments, we use Function#apply to call it, because Function#apply takes an array and then calls a function with records from the array as discrete arguments.

Note : $.when resolves the promise it returns when all of the promises you give it are allowed or rejects its promise when any of the promises you give is rejected. Therefore, if one of the ajax calls fails, you will immediately receive your callback , even if other calls are still being issued .

If you do not want this, then you need to write your own function, which is not difficult; something like that:

 function waitForAll(promises) { var waitingFor = promises.length; var allGood = true; var oneResolved = oneSettled.bind(null, true); var oneRejected = oneSettled.bind(null, false); var d = $.Deferred(); promises.forEach(function(promise) { promise.then(oneResolved, oneRejected); }); return d.promise(); function oneSettled(resolved) { if (!resolved) { allGood = false; } if (--waitingFor === 0) { if (allGood) { d.resolve(); } else { d.reject(); } } } } 

It just waits for them all, and then either allows or rejects, depending on whether any of them worked. You can take it further, allow or reject it using an array of results.


You can make $.when with the array a little more convenient by providing yourself a utility function:

 function whenAll(array) { return $.when.apply($, array); } 

... and then:

 whenAll($.map(array, function(k, v) { return $.ajax({ ... }); })).then(function() { // They're all done now }); 

You can even add this to $ , but of course, a future version of jQuery may define whenAll , so be careful.

+12
source

All Articles