jquery deferred - "always" called at the first reject
javascript, jquery, jquery-deferred
Solution
It's by design: The method will resolve its master Deferred as soon as all the Deferreds resolve, or reject the master Deferred as soon as one of the Deferreds is rejected. [...] Note that some of the Deferreds may still be unresolved at that point.
http://api.jquery.com/jQuery.when/
You can save references to all deferreds and track them separately.
Something like this:
var whenAll = function() {
var dfd = $.Deferred(),
len = arguments.length,
counter = 0,
state = "resolved",
resolveOrReject = function() {
if(this.state() === "rejected"){
state = "rejected";
}
counter++;
if(counter === len) {
dfd[state === "rejected"? "reject": "resolve"]();
}
};
$.each(arguments, function(idx, item) {
item.always(resolveOrReject);
});
return dfd.promise();
};
http://jsfiddle.net/cSy2K/2/
Problem
I'm using `$.when` to chain some Deferred objects, and if one of them fail, the `always` method will be called directly after the failure, even if I still have some deferrer in a "pending" state. ``` var promises = [], defs = []; for(var i=0 ; i < 10 ; i++){ defs.push($.Deferred()); promises.push(defs[i].promise()); } var res = $.when.apply($, promises); res.fail(function(){console.log('failed')}); res.done(function(){console.log('done')}); res.always(function(){console.log('always')}); res.then(function(){console.log('then, done')}, function(){console.log('then, failed')}); var j = 0; var t = setInterval(function(){ if(j < 10){ if(j < 5) { console.log('resolve'); defs[j++].resolve(); } else { console.log('reject'); defs[j++].reject(); } } else { clearInterval(t); } }, 200); ``` Check this jsfiddle. Maybe it's the normal behavior. But, in this case, how can I catch the end of my chain even if some of them have failed?