Jquery 链中延迟和多个延迟

Jquery Deferred and multiple deferred in chain

求助:

例如,我有 20 个超时,由 window.setTimeout 创建,我希望它们 运行 一个接一个:

调用超时 1 => 完成调用超时 2 => 完成调用超时 3 等等。

一般是函数数组,超时次数不固定

我的延迟函数:

function someFunction(index) {
   console.log("someFunction called, index = " + index);
   var $deferred = $.Deferred();

   window.setTimeout(function () {
       $deferred.resolve();
   }, 2000);

   return $deferred.promise();
}

循环:

var $deferred;
$(someArray).each(function (index) {
    if (!$deferred) {
        $deferred = someFunction(index);
    } else {
        $deferred.then(function () {
            return someFunction(index);
        });
    }
});

其他都是运行直接不在链中

如果你想将它们一个接一个地链接起来,你必须这样做:

var $deferred;
$(someArray).each(function (index) {
    if (!$deferred) {
        $deferred = someFunction(index);
    } else {
        $deferred = $deferred.then(function () {
            return someFunction(index);
        });
    }
});

您所做的是将所有 .then() 处理程序放在同一个 deferred 上,这将 运行 它们全部并行,而不是串行。你需要的是 p.then(...).then(...).then(...) 的等价物。由于每个 .then() returns 一个新的承诺,您需要链接到链中的下一个 link。


您可能会发现此设计模式对于使用生成承诺的异步操作顺序遍历数组来说更简单一些:

someArray.reduce(function(p, item) {
    return p.then(function() {
        return someFunction(item);
    });
}, $.Deferred().resolve()).then(function() {
    // all done here
});

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

尝试使用 $.queue() , $.dequeue() , $.map()

function someFunction(index) {
  console.log("someFunction called, index = " + index);
  var $deferred = $.Deferred();

  window.setTimeout(function() {
    $deferred.resolve();
  }, 2000);

  return $deferred.promise();
}

var someArray = [1, 2, 3, 4, 5];

$.queue(someArray, "dfd", $.map(someArray, function(value, index) {
  return function(next) {
    someFunction(index).then(next)
  }
}));
$.dequeue(someArray, "dfd");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>

两种方法都有效:

$.queue(someArray, "dfd", $.map(someArray, function(value, index) {
  return function(next) {
    someFunction(index).then(next)
  }
}));
$.dequeue(someArray, "dfd");

someArray.reduce(function(p, item) {
    return p.then(function() {
        return someFunction(item);
    });
}, $.Deferred().resolve()).then(function() {
    // all done here
});