在承诺完成后运行返回承诺的函数

时间:2016-05-06 20:14:16

标签: javascript node.js asynchronous promise bluebird

我有一系列需要执行的函数。 这些功能都回报了承诺。

我想在系列中运行所有函数,但只有在完成上一个函数的承诺后才能启动下一个函数。

我认为使用async或bluebird库会很容易,但我找不到一个简单的解决方案。

这是我做的(未经测试),但我一直在寻找标准库解决方案,因为这可能已经存在了?

function runFuncs(funcs) {

    function funcRunner(funcs, resolve, reject, pos=0) {
        funcs[pos]().then(function() {
            pos++;
            if (pos < length(funcs)) {
                funcRunner(funcs, pos);
            } else {
                resolve();
            }
        }).catch(function(err) {
            reject(err);
        });
    }

    return new Promise(function(resolve, reject) {
        funcRunner(funcs, resolve, reject);
    });
}

4 个答案:

答案 0 :(得分:4)

如果每个函数都返回一个promise本身,你可以将它们链接在一起。这样的事情应该有效:

function runFuncs(funcs) {
  return funcs.reduce(function (p, funcToRun) {
      return p.then(function () {
        return funcToRun();
      });
  }, Promise.resolve(null));
}

基本上,你只是将承诺链接在一起。根据链的性质,如果从then处理程序返回一个promise,那将成为最终的承诺。因此,reduce调用遍历数组中的每个promise,在其上执行then以处理数组中的下一个。

答案 1 :(得分:1)

我知道你已经标记了一个答案,但我还不能发表评论并且不得不问:你的例子似乎没有将结果从一个函数传递到另一个函数,你真的需要它们串行运行吗?

如果系列是一项硬性要求,Bluebird的.mapSeries()方法将完全符合您的要求,并且代码非常简洁。否则,您可以交换.map()并利用并发性来并行完成任务。

Promise.mapSeries(fnArray, (fn) => 
{
    return fn(...);
})
.then((results) =>
{
    // do something with the results.
});

或与.map()

并行
Promise.map(fnArray, (fn) => 
{
    return fn(...);
}, 
{ concurrency: 5 })
.then((results) =>
{
    // do something with the results.
});

答案 2 :(得分:0)

不使用额外的库,只使用普通的旧JS代码,我能够提出一个简单的解决方案。

'use strict';

// Create an array of functions that return a promise
const promises = [];
let i = 0;
while (i++ < 10) {
  const v = i;
  promises.push(() => {
    return new Promise( (resolve, reject) => {
      setTimeout(() => {
        resolve(v);
      }, Math.floor(Math.random() * 1000));
    });
  });
}

function nextPromise(idx) {
  if (idx >= promises.length) return;
  promises[idx]().then((v) => {
    console.log("Resolved", v);
    nextPromise(++idx);
  });  
}

nextPromise(0);

在这个例子中,我创建了一个包含10个函数的数组,每个函数返回一个promise,它在随机的毫秒数之后解析一个单调递增的数字。

要按顺序执行它们,我只使用一些递归。这是一个看起来很丑的hackey代码,但它确实有效。

答案 3 :(得分:0)

如果&#34; funcs&#34;是承诺数组,你可以使用Promise.all() - Promise docs

import {Promise} from 'es6-promise';

const runFuncs = funcs => {
  return Promise.all(funcs);
};

export default runFuncs;