乒乓球行为使用deffered

ping pong behaviour using deffered

本文关键字:deffered 乒乓球      更新时间:2023-09-26

我创建了以下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,该promise在输出消息时得到解析
  2. 函数run()接受多个循环和两个值的数组以在它们之间交替
  3. 函数next()检查是否还有循环要运行,如果有,则将两个go()操作链接在一起,当最后一个操作完成时,递减循环数,然后再次调用next()

您的实现有各种各样的问题:

  1. 给定的延期或承诺只能解决或拒绝一次
  2. $.when()接受了一个承诺列表,所以$.when($, dfd)是错误的
  3. 当只有一个promise时,甚至不需要$.when(),因为您可以直接在promise上使用.then()
  4. 你的for循环不会在承诺之间暂停,所以你的所有"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/

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

  • 一旦延期得到解决,以后就不能(我相信)拒绝。正如本问题中所讨论的,它们是一次性使用对象。

  • 其次,在pong之前获取所有ping,因为输出ping的机制是同步机制(循环)。然而,输出pong的机制是异步的——超时。因此,从有效的角度来看,ping都是在同一个过程实例中输出的,而pong直到3秒后才开始——在ping输出很久之后。