我有一系列需要执行的函数。 这些功能都回报了承诺。
我想在系列中运行所有函数,但只有在完成上一个函数的承诺后才能启动下一个函数。
我认为使用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);
});
}
答案 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;