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?
-
I'm pretty sure it's not defined. It shouldn't really be defined and you should never need to rely on it.ForbesLindesay– ForbesLindesay2013-05-01 03:04:08 +00:00Commented May 1, 2013 at 3:04
-
4It's very defined. First, either fail or done will be called. Next, always will be called. It can't be in any other order. The callbacks will trigger fifouser400654– user4006542013-05-01 03:04:43 +00:00Commented May 1, 2013 at 3:04
-
7FIFO rules: DEMO.Beetroot-Beetroot– Beetroot-Beetroot2013-05-02 12:23:21 +00:00Commented May 2, 2013 at 12:23
-
3As @Beetroot-Beetroot's demo makes clear, it is entirely fifo and not as Kevin-B suggests that done/fail precedes always. Someone should make Beetroot-Beetroot's comment the answer - it appears to be correct and definitive.Rob Murphy– Rob Murphy2014-04-30 09:10:54 +00:00Commented Apr 30, 2014 at 9:10
2 Answers
@Malcolm's answer is indeed correct. The docs mention it in many places, including:
deferred.done()anddeferred.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."
Implementation details
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 aforloop.
Comments
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.