Reputation: 12112
Jquery's $.when
function executes the 'done' callback when all promises are resolved, but not if any of them result in errors. How do I execute the 'done' callback once all the promises have had a result, either success
or error
?
Upvotes: 1
Views: 617
Reputation: 276306
Jquery's $.when function executes the 'done' callback when all promises are resolved, but not if any of them result in errors.
Allow me to rephrase that in more accurate terminology.
jQuery's $.when
takes a list of promises1 and returns a new promise. That new promise fulfills when all of those promises fulfill or rejects when any of those promises reject.
The function you're looking fall is called "Settle" and is unavailable in jQuery's promise implementation - luckily we can easily add it.
The strategy is:
n
- the number of arguments.$.settle = function(promises){
var count = arguments.length; // how many we'll have to wait for
var d = $.Deferred(); // the new deferred - representing the return value
var results = []; // what we'll end up resolving with
$.map(arguments, function(arg, i){
if(typeof arg.then !== "function"){ // it's not a promise!
results[i] = {status:"fulfilled", value: arg};
count--; // and we don't have to wait for it
} else {
arg.then(function(value){
results[i] = {status:"fulfilled", value: value };
count--;
if(count === 0) d.resolve.apply(d, results); // resolve promise
}, function(e){
results[i] = {status:"rejected", reason: e };
count--;
if(count === 0) d.resolve.apply(d, results); // resolve promise
});
}
})
return d.promise(); // return a promise over the deferred
}
The usage of the above should something like:
$.settle($.get("firstUrl"),$.get("secondUrl")).then(function(firstResult, secondResult){
// access results here, values are in firstResult.value
// and you can tell if it rejected or fulfilled in firstResult.status
);
I'm not a huge fan of the semantics here - but I've tried to keep them as close as possible to jQuery's semantics for $.when
.
(1. or deferreds which are also promises in jQuery)
Upvotes: 1