jQuery Deferred and Promise for sequential execution of synchronous and asynchronous functions

21,803

Solution 1

For jQuery prior to 1.8, this is a problem, but for new versions of jQuery, this is not a problem anymore:

function test(){
  var d = jQuery.Deferred(), 
  p=d.promise();
  //You can chain jQuery promises using .then
  p.then(a).then(b).then(c);
  d.resolve();
}
test();

DEMO

Below is the demo of jQuery 1.7.2

DEMO

Solution 2

jQuery < 1.8 is fine WRT chaining, you just use .pipe instead of .then. 1.8 simply changed .then to be .pipe.

Solution 3

Sidenote: When you use it without the array, you don't have to start with a promise. $.when({}).then(a).then(b) will do the trick just fine. You only need to make sure you don't put a inside the when.

Share:
21,803

Related videos on Youtube

HMR
Author by

HMR

Like programming because interest me. Love getting paid for my hobby. I am available for mentoring, just send a message to harmmeiier at the gmail com.

Updated on July 09, 2022

Comments

  • HMR
    HMR almost 2 years

    If I want to have synchronous and asynchronous functions execute in a particular order I could use jQuery promise but it doesn't seem to work the way I'd expect it to work.

    Functions a,b and c should execute in that order when in a the deferred.resolve() is called I'd expect function b to be executed but all functions are executed immediately no matter if the resolve is called.

    Here is the code:

    function a(){
      var deferred = $.Deferred();
      setTimeout(function(){
        console.log("status in a:",deferred.state());
        //this should trigger calling a or not?
        deferred.resolve("from a");
      },200);
      console.log("a");
      return deferred.promise();
    };
    function b(){
      var deferred = $.Deferred();
      setTimeout(function(){
        console.log("status in b:",deferred.state());
        deferred.resolve("from b");
      },200);
      console.log("b");
      return deferred.promise();
    }
    //synchronous function
    function c(){
      var deferred = $.Deferred();
      console.log("c");
      console.log("status in c:",deferred.state());
      deferred.resolve("from c");
      return deferred.promise();
    }
    function test(){
      fn=[a,b,c],i=-1,
      len = fn.length,d,
      d = jQuery.Deferred(),
      p=d.promise();
      while(++i<len){
        p=p.then(fn[i]);
      }
      p.then(function(){
        console.log("done");
      },
      function(){
        console.log("Failed");
      });
      d.resolve();
      //instead of the loop doing the following has the same output
      //p.then(a).then(b).then(c);
      //d.resolve();
    }
    test();
    

    Output is:

    a
    b
    status in c: pending
    c
    done
    status in a: pending
    status in b: pending
    

    Expected output:

    a
    status in a: pending
    b
    status in b: pending
    c
    status in c: pending
    done
    

    Tried a some combinations of the following modifications:

      d = jQuery.Deferred();
      setTimeout(function(){d.resolve();},100);
      var p=d.promise();
      while(++i<len){
        p.then(fn[i]);
      }
    

    But all with same unexpected results, b gets called before deferred of a is resolved, c is called before deferred of b is resolved.

  • A. Wolff
    A. Wolff over 10 years
    As a side note, to get it works in jquery 1.7.2 (using extend jq native code) jsfiddle.net/L5nud/2
  • Esailija
    Esailija over 10 years
    jQuery < 1.8 is fine WRT chaining, you just use .pipe instead of .then. 1.8 simply changed .then to be .pipe.
  • Cristian
    Cristian almost 10 years
    how to use it, if a function return a value that use b function and so on.
  • Khanh TO
    Khanh TO almost 10 years
    @Cristian Chaparro A. The returned value of a function is passed as an argument to b function.