使用deffered的乒乓行为

我创建了以下javascript代码:

var index, _i; var dfd = new $.Deferred(); dfd.resolve(); for (index = _i = 0; _i < 10; index = ++_i) { $.when($, dfd).done(function() { console.log('ping'); promise = (function(index) { setTimeout(function() { console.log('pong'); dfd.resolve(); }, 3000); dfd.reject(); })(index); }) } 

在控制台中我看到以下结果

 ping ping ping ping ping ping ping ping ping ping pong pong pong pong pong pong pong pong pong pong 

但我想实现

 ping pong ping pong .... 

我在哪里错了,如何根据我想要的行为重写代码?

这是一种方法:

 function go(val, t) { var def = $.Deferred(); setTimeout(function() { log(val); def.resolve(); }, t); return def.promise(); } function run(numCycles, values, delay) { function next() { if (numCycles > 0) { go(values[0], delay).then(function() { return go(values[1], delay); }).then(function() { --numCycles; next(); }); } } next(); } run(10, ["ping", "pong"], 500); 

工作演示: http : //jsfiddle.net/jfriend00/g0Lxm3ws/

从概念上讲,这是如何工作的:

  1. 函数go()在定时器后输出一条消息。 它返回一个在输出消息时解析的promise。
  2. 函数run()接受多个循环和两个值的数组以在它们之间交替。
  3. 函数next()检查是否还有更多周期要运行,如果是,则将两个go()操作链接在一起,当最后一个完成时,减少周期数,然后再次调用next()

您的实施存在各种问题:

  1. 给定的延期或承诺只能被解决或拒绝一次。
  2. $.when()接受一个承诺列表,所以$.when($, dfd)是错误的。
  3. $.when()只有一个promise时,甚至不需要$.when()因为你可以直接在promise上使用.then()
  4. 您的for循环不会在promises之间暂停,因此所有"ping"消息将立即出现,然后"pong"消息将在稍后出现。

仅供参考,如果你想循环一个任意数组的值,你可以这样做:

 function go(val, t) { var def = $.Deferred(); setTimeout(function() { log(val); def.resolve(); }, t); return def.promise(); } function run(numCycles, values, delay) { function next() { if (numCycles > 0) { // create initial resolved promise // for start of a .reduce() chain var d = $.Deferred().resolve().promise(); values.reduce(function(p, val){ return p.then(function() { return go(val, delay); }); }, d).then(function() { --numCycles; next(); }); } } next(); } run(5, ["tic", "tac", "toe"], 500); 

工作演示: http : //jsfiddle.net/jfriend00/1ckb6sg6/

我必须说我不知道​​你是如何得到这种代码或者你真正想要实现的。 但是,至少回答你的第一个问题(出了什么问题?):

  • 一旦延期解决,它(我相信)以后就不会被拒绝。 如本问题所述 ,它们旨在作为一次性使用对象。

  • 其次,你在pongs之前得到所有的ping,因为ping的输出机制是同步的(循环)。 然而,输出拨弦的机制是异步的 – 超时。 因此,在有效的条件下,ping都是在相同的程序实例中输出的,而在3秒之后 – 在输出ping之后很长时间内,它不会启动。