使用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/
从概念上讲,这是如何工作的:
- 函数
go()
在定时器后输出一条消息。 它返回一个在输出消息时解析的promise。 - 函数
run()
接受多个循环和两个值的数组以在它们之间交替。 - 函数
next()
检查是否还有更多周期要运行,如果是,则将两个go()
操作链接在一起,当最后一个完成时,减少周期数,然后再次调用next()
。
您的实施存在各种问题:
- 给定的延期或承诺只能被解决或拒绝一次。
-
$.when()
接受一个承诺列表,所以$.when($, dfd)
是错误的。 -
$.when()
只有一个promise时,甚至不需要$.when()
因为你可以直接在promise上使用.then()
。 - 您的
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之后很长时间内,它不会启动。