Search code examples
jqueryjquery-deferreddeferred

what is the difference between these pattern of jquery defered call?


I am trying to call some asynchronous function like this. Why in case A and case B I failed but success in case C?

Case A

firstCall()// try to get esstential parameters(a defered)
.fail(function(){
   //failed :call login function again wait user to input login credential(also a defered)
})
.always(function() {
    //show welcome message
})    

In this case when fail just start to execute, the always part just execute without waiting.

Case B

firstCall()// try to get esstential parameters(a defered)
.fail(function(){
    //failed :call login function again wait user to input login 
})
.done(function() {
    //show welcome message
})

In this case,if the fail part get executed ,but the done part never get executed.

Case C

firstCall()// try to get esstential parameters(a defered)
.then(null,function(){
     //failed :call login function again wait user to input login 
})
.always(function() {
    //show welcome message
})

In this case, the then part act as the fail part, and always can run after then finished.

I am not sure why is the case happening.Can someone explained further? Thanks


Solution

  • All external quotes in this answer are taken from the jQuery Deferred Object documentation or the corresponding method documentation linked therein.


    CASE A

    "...the always part just execute without waiting."

    Let''s take a look at the documentation for .fail():

    ...deferred.fail() returns the deferred object, other methods of the deferred object can be chained to this one...

    The .fail() method returns the original deferred object rather than opening a new promise. What this means is that any events chained to it, while they will run sequentially, do not inherently wait for the previous ones to finish. Your .fail() will not be awaited, but executed instantly.

    Any callback methods you'd like to attach would have to be chained to the inner function, creating a nested cycle of deferred objects - you can imagine how ugly that might get if we started going three or four callbacks deep.

    Luckily, .then() exists for this exact purpose! But more on that in Case C...


    CASE B - "In this case,if the fail part get executed ,but the done part never get executed."

    .done() and .fail() are opposites. Only one of them will fire for any single deferred object, based on whether it succeeds or fails.

    deferred.done()

    Add handlers to be called when the Deferred object is resolved.

    deferred.fail()

    Add handlers to be called when the Deferred object is rejected.


    CASE C

    .then()

    Add handlers to be called when the Deferred object is resolved, rejected, or still in progress.

    .then() and .fail() both handle a rejected deferred object.

    However there is a major difference:

    As of jQuery 1.8, the deferred.then() method returns a new promise...

    .then() returns a new promise, whereas .fail() does not. This means that any methods chained to the .then() method will await its completion much like the original deferred object.


    Summary:

    If you're trying to make sequential awaited calls, use .then(). This will allow you to progress through the chain as a sequence of new promises, while maintaining the status and values of the original deferred object.

    If you're finished making sequential calls and you're ready to "close" the deferred object, use a method that returns the deferred object, like .done(), .fail(), or.always().