运行 功能 return 在承诺完成后连续承诺

Run functions that return promises in series after promise is done

我有一组函数需要执行。 这些功能都是 return 一个承诺。

我想运行串联所有的功能,但是只有完成上一个功能的promise才能启动下一个功能

我认为使用 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);
    });
}

如果每个函数 return 本身就是一个 promise,您可以将它们链接在一起。这样的事情应该有效:

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

基本上,您只需将承诺链接在一起即可。根据链的性质,如果您 return 来自 then 处理程序的承诺,它就会成为结果承诺。所以 reduce 调用遍历数组中的每个 promise,对其执行 then 以处理数组中的下一个。

不使用额外的库,只使用普通的旧 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 个函数的数组,每个函数 returns 一个在随机毫秒数后解析单调递增数字的承诺。

为了按顺序执行它们,我只使用了一些递归。这是一种看起来有点丑陋的 hackkey 代码,但它确实有效。

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

如果系列是一项硬性要求,Bluebird 的 .mapSeries() method will do exactly what you're looking for, and the code is incredibly neat. Otherwise you can swap in .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.
});

如果 "funcs" 是承诺数组,您可以使用 Promise.all() - Promise docs

import {Promise} from 'es6-promise';

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

export default runFuncs;