Reputation: 307
jQuery's Deferred/promise has two outcomes: resolved and rejected. You can attach callbacks to the Deferred which are associated with either state. The conditions for attachment are done (associated with resolved), fail (associated with rejected), and always (associated with both states). I have unsuccessfully been trying to determine the sequence of the callbacks when the state moves from pending to non-pending; i.e., for done and always (or fail and always), what is the sequence in which the callbacks execute for each state of resolved and rejected?
Upvotes: 20
Views: 6188
Reputation: 8602
@Malcolm's answer is indeed correct. The docs mention it in many places, including:
deferred.done()
and deferred.fail()
– "Callbacks are executed in the order they were added."deferred.always()
– "When the Deferred is resolved or rejected, callbacks are executed in the order they were added"jQuery.ajax()
– "Promise callbacks — .done()
, .fail()
, .always()
, and .then()
— are invoked, in the order they are registered."Looking at the Deferred module, it uses the Callbacks module which implements a FIFO "callback list".
Here's the call stack for adding callbacks to a Deferred object:
always()
done()
/ fail()
Callbacks.add()
list.push()
– The callback function is pushed onto the end of the list.And here's the call stack for resolving/rejecting the Deferred object:
resolve()
/ reject()
resolveWith()
/ rejectWith()
Callbacks.fireWith()
Callbacks.fire()
– The callbacks in the list are executed in FIFO order using a for
loop.Upvotes: 14
Reputation: 5009
Deferred objects process their callbacks in the order that the callback was added to the deferred object. There is no precedence to done()
over always()
, or vice versa. The behavior is identical whether you call resolved()
or reject()
.
Please see the following jsfiddle example.
The comments on the original question are not correct, or at least not completely correct.
Upvotes: 6