Wait until all jQuery ajax calls are completed (done or rejected)

1.3k views Asked by At

I've looked through many similar questions but the proposed solutions do not work in all cases as expected. The following code works fine when all ajax calls are successfully done but if any of ajax calls happens to fail, then onComplete is immediately called:

var deferredArray = $('.preload').map(function() {
    return $.get(this.href)
});
$.when.apply($, deferredArray).then(onComplete, onComplete);

So there can be two cases:

  • all deferred calls are successful, then onComplete is called afterwards - works fine;
  • some deferred call fails (returns HTTP 400 Bad request), then onComplete is called immediately not waiting for other deferred calls.

The second case represents my problem. It should always wait for all calls to complete regardless of the status before calling onComplete.

I use jQuery 1.7.1 as it's built into the framework. If the issue is due to the version, I can upgrade but I'd prefer to keep the current version.

2

There are 2 answers

0
khollenbeck On

You could try ajaxStop(). Allbeit not the most elegant solution.

$( document ).ajaxStop(function() {
  // do some stuff now that all the ajax stuff has stopped
})

Also note:

If $.ajax() or $.ajaxSetup() is called with the global option set to false, the .ajaxStop() method will not fire.

0
RoboKozo On

I'm not sure if this outside of the scope of the types of solutions you're looking for, but I've recently been taking advantage of bluebird.js to wrap all my jquery ajax calls.

For example:

Promise.resolve($.get("http://www.google.com")).then(function() {});

What this allows me to do is then perform a Promise.all which will then wait for all the ajax calls to be complete. Each individual promise can pass or fail, but .then (or .spread) on the .all will only be called if they all succeed.

var aPass = function(){
    return Promise.resolve($.get("/echo/json/"))
};

var aFail = function(){
    return Promise.resolve($.get("/echo/jsonFake/")) // this will fail
};

var allPass = [aPass(), aPass(), aPass()];

var oneFails = [aPass(), aPass(), aFail()];


Promise.all(allPass).spread(function(a,b,c){
    console.log("All Done!");
}).catch(function(){
    console.log("NEVER FAILS!");
});;

Promise.all(oneFails).spread(function(a,b,c){
    console.log("never goes in here");
}).catch(function(){
    console.log("FAILED");
});

Here is a jsfiddle demonstrating this: http://jsfiddle.net/ys598t4s/2/