Johan
Johan

Reputation: 35223

deferred.always() fires too early

var xhr1 = $.ajax({ url:'/echo/json/', data:{ delay: 3 } }),
    xhr2 = $.ajax({ url:'/echo/json/something/invalid', data:{ delay: 3 } });

xhr1.always(function(){
    console.log('xhr1 always');
});

xhr2.always(function(){
    console.log('xhr2 always');
});

$.when.apply($, [xhr1, xhr2]).always(function(){
    console.log('xhr1 & xhr2 always');
});

Result (console):

xhr2 always
xhr1 & xhr2 always
xhr1 always 

Why doesn't deferred.always() wait for both ajax calls to be completed? Is there any defered callback which can be used when all requests are done, regardless of their status?

http://jsfiddle.net/W9A3f/

Upvotes: 0

Views: 306

Answers (1)

Alnitak
Alnitak

Reputation: 340055

The .when(...) will trigger its callbacks when all of them are resolved, or as soon as any of them are rejected.

Since the second AJAX call results in an error, the .when().always() happens as soon as the second AJAX call error happens, whether or not the first AJAX call succeeded yet or not.

The only solution I know of for your scenario is to keep a second $.Deferred around for each AJAX request, and then resolve those in each AJAX request's always handler. Then use those deferreds in your $.when call:

var def1 = $.Deferred();
xhr1.always(def1.resolve);

var def2 = $.Deferred();
xhr2.always(def2.resolve);

$.when(def1, def2).done(function() {
    // only called when the two XHRs complete, whether
    // they succeeded or not
});

Upvotes: 4

Related Questions