jQuery Deferred和Promise用于同步和异步函数的顺序执行

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

本文关键字:函数 顺序 异步 执行 同步 Deferred Promise 用于 jQuery      更新时间:2023-09-26

如果我想让同步和异步函数按特定顺序执行,我可以使用jQuery promise,但它似乎没有按我期望的方式工作。

当在a中调用deferred.resolve()时,函数a、b和c应该按该顺序执行。我希望函数b会被执行,但无论是否调用resolve,所有函数都会立即执行。

这是代码:

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();

输出为:

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

预期输出:

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

尝试了以下修改的一些组合:

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

但所有这些都有相同的意外结果,b在a的deferred被解析之前被调用,c在b的deferrd被解析之前调用。

对于1.8之前的jQuery,这是一个问题,但对于jQuery的新版本,这不再是问题:

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();

演示

下面是jQuery 1.7.2 的演示

演示

jQuery<1.8是很好的WRT链接,您只需要使用.pipe而不是.then。1.8简单地将CCD_ 4改变为CCD_。

旁注:当您在没有数组的情况下使用它时,您不必从promise开始。$.when({}).then(a).then(b)会很好地发挥作用。你只需要确保你没有把a放在when里面。