Imagine a scenario where we want to do something after the concurrent requests for 'foo' and 'bar' have completed successfully, or report an error if one or both of them fails:
$.when($.getJSON('foo'), $.getJSON('bar'))
.then(function(foo, bar) {
console.log( 'I fire if BOTH requests are successful!' );
})
.fail(function() {
console.log( 'I fire if one or more requests failed.' );
});
How can I determine if 1) the request for 'foo' failed, or 2) the request for 'bar' failed, or 3) if both failed?
Simply add a fail call to each promise that is returned from $.getJSON
:
function make_error_handler(msg) {
return function() { console.log(msg); };
}
$.when($.getJSON('foo').fail(make_error_handler("foo failed"))
, $.getJSON('bar').fail(make_error_handler("bar failed")))
.then(function(foo, bar) {
console.log( 'I fire if BOTH requests are successful!' );
})
.fail(function() {
console.log( 'I fire if one or more requests failed.' );
});
If you need more fine-grained control you can overload $.getJSON
to return additional information to the fail function -- see jQuery's documentation on deferred.rejectWith
From the documentation on jQuery.when
In the multiple-Deferreds case where one of the Deferreds is rejected, jQuery.when immediately fires the failCallbacks for its master Deferred. Note that some of the Deferreds may still be unresolved at that point. If you need to perform additional processing for this case, such as canceling any unfinished ajax requests, you can keep references to the underlying jqXHR objects in a closure and inspect/cancel them in the failCallback.
In other words, you are supposed to keep the references to each request, and check it manually yourself, if you need to.
The difficulty is that when the fail callback is called, any number of deferred's can still be outstanding, thus at that state they have neither failed nor succeeded.
I wish the documentation explained a bit better as to exactly what is passed to the fail handler in this case. Judging from the source code though, it seems that the arguments received by the fail handlers depend on which Deferred fails first:
args[ i ].promise().then( resolveFunc(i), deferred.reject );
I'm no expert on jQuery internals, but I think this simply lets each of your Deferred's call the "master" Deferred's reject
method with whatever arguments it would normally pass to its handlers. Not ideal, if you ask me... but then I could be misreading this.
I do wonder if they meant this though:
args[ i ].promise().then( resolveFunc(i), func() { deferred.reject(args); } );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With