Reputation: 12740
Basically this is what I'm trying to do in pseudo-code:
Fetch AsyncResultA
If Success
Fetch
AsyncResultB
AsyncResultC
Either Success/Fails
Display any successful results
If Fails
Display error
And this is what I've done in jQuery but it doesn't work:
$.when (
fetchA()
).then (function (data, textStatus, jqXHR) {
return {
xhrObject1: [data, textStatus, jqXHR],
xhrObject2: fetchB(),
xhrObject3: fetchC(),
xhrObject4: fetchD()
}
}, fail
).always( displayResults );
Notes:
All fetch
functions are AJAX calls.
displayResults
would get the successful fetched data and displays it all at once. So as long as fetchA
succeeds, something would display.
fail
would only get called when fetchA
fails, thus canceling any further fetches.
Upvotes: 2
Views: 1317
Reputation: 817238
It doesn't work because you are not returning a promise from the .then
callback, but an ordinary object. That has the effect that displayResults
is basically called on the original promise returned by fetchA
instead. The relevant part from the documentation (emphasis mine):
As of jQuery 1.8, the
deferred.then()
method returns a new promise [...]. These filter functions can return a new value to be passed along to the promise's.done()
or.fail()
callbacks, or they can return another observable object (Deferred, Promise, etc) which will pass its resolved / rejected status and values to the promise's callbacks.
Use $.when
and return its return value:
fetchA().then(function () {
return $.when([].slice.call(arguments), fetchB(), fetchC(), fetchD());
}, fail).always( displayResults );
$.when
returns a promise that is resolved when all the promises passed to itself are resolved (or rejected). Therefore is no reason to use $.when
if you only pass a single argument to it.
If you don't want to execute displayResults
when fetchA
fails, you can bind the fail handler separately:
fetchA().fail(fail).then(function () {
return $.when([].slice.call(arguments), fetchB(), fetchC(), fetchD());
}).always( displayResults );
Upvotes: 3