如何在Q中按顺序链接可变数量的promise?

Che*_*eso 32 node.js promise q

在Q中看到Chaining任意数量的承诺 ; 我的问题不同.

如何按顺序进行可变数量的调用,每个调用都异步返回?
该场景是一组HTTP请求,其数量和类型由第一个HTTP请求的结果确定.

我想简单地这样做.

我也看到过这样的答案:

var q = require('q'),
    itemsToProcess =  ["one", "two", "three", "four", "five"];

function getDeferredResult(prevResult) {
  return (function (someResult) {
    var deferred = q.defer();
    // any async function (setTimeout for now will do, $.ajax() later)
    setTimeout(function () {
      var nextResult = (someResult || "Initial_Blank_Value ") + ".." + itemsToProcess[0];
      itemsToProcess = itemsToProcess.splice(1);
      console.log("tick", nextResult, "Array:", itemsToProcess);
      deferred.resolve(nextResult);
    }, 600);

    return deferred.promise;
  }(prevResult));
}

var chain = q.resolve("start");
for (var i = itemsToProcess.length; i > 0; i--) {
    chain = chain.then(getDeferredResult);
}
Run Code Online (Sandbox Code Playgroud)

...但以这种方式循环itemsToProcess似乎很尴尬.或者定义一个名为"loop"的新函数来抽象递归.什么是更好的方式?

Stu*_*t K 75

有一个很好的清洁方式[].reduce.

var chain = itemsToProcess.reduce(function (previous, item) {
    return previous.then(function (previousValue) {
        // do what you want with previous value
        // return your async operation
        return Q.delay(100);
    })
}, Q.resolve(/* set the first "previousValue" here */));

chain.then(function (lastResult) {
    // ...
});
Run Code Online (Sandbox Code Playgroud)

reduce迭代数组,传入上一次迭代的返回值.在这种情况下,你将返回承诺,所以每次你链接一个then.你提供了一个初步的承诺(正如你所做的那样q.resolve("start")).

起初可能需要一段时间来围绕这里发生的事情,但如果你花点时间来完成它,那么这是一个易于使用的模式,无需设置任何机器.

  • 这是f****心灵弯曲.但仍然很棒;) (10认同)