Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 238
HMR Avatar asked Nov 21 '13 13:11

HMR


People also ask

What is JQuery deferred and promise object?

A deferred object is an object that can create a promise and change its state to resolved or rejected . Deferreds are typically used if you write your own function and want to provide a promise to the calling code. You are the producer of the value. A promise is, as the name says, a promise about future value.

What is deferred function in JQuery?

Deferred() A factory function that returns a chainable utility object with methods to register multiple callbacks into callback queues, invoke callback queues, and relay the success or failure state of any synchronous or asynchronous function.

Are JQuery functions synchronous?

You can use jQuery to support both synchronous and asynchronous code, with the `$. when` function, and your code doesn't have to care whether or not it's async.

What is the use of promise in JQuery?

promise() method returns a dynamically generated Promise that is resolved once all actions of a certain type bound to the collection, queued or not, have ended. By default, type is "fx" , which means the returned Promise is resolved when all animations of the selected elements have completed.


1 Answers

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

like image 94
Khanh TO Avatar answered Sep 19 '22 21:09

Khanh TO