jQuery的延迟对象和承诺对象:用于同步和异步函数的顺序执行

13

如果我想要同步和异步函数按特定顺序执行,我可以使用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的延迟解决之前就被调用了,c在b的延迟解决之前被调用了。

3个回答

9

对于jQuery 1.8之前的版本,这是一个问题,但对于新版本的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的演示。

演示


1
顺便提一下,为了使其在jquery 1.7.2中工作(使用扩展jq本地代码)http://jsfiddle.net/L5nud/2/ - A. Wolff
1
jQuery < 1.8就链式调用而言没有问题,只需使用.pipe代替.then即可。1.8版本只是将.then更改为.pipe。 - Esailija
如何使用它,如果a函数返回一个值,该值使用b函数等等。 - Cristian
@Cristian Chaparro A. 函数 a 的返回值作为参数传递给函数 b - Khanh TO

2

对于链式调用,jQuery版本 < 1.8 使用.pipe,而不是.then。 1.8 版本将.then更改为.pipe


1

附注:当你不使用数组时,你不需要以一个promise开始。 $.when({}).then(a).then(b)也可以完美地解决问题。你只需要确保你不把a放在when里面。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接