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?
Yes, it is normal behavior. If one fails, the thing that relies on all fails as well. See also the jQuery docs.
So, you either have to track them manually, or you feed only resolved Promises into
when
:With this, your
res
will only call thedone
callback when all promises are processed, and it will get an array of objects indicating status and result of them.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:
http://jsfiddle.net/cSy2K/2/