我是新的承诺.
我遇到了一个需要循环执行一系列任务并获取数据的情况.出于某种原因,我必须按顺序进行,并且必须使用promises来完成.但令我惊讶的是,结果只有最后一个元素而不是所有元素.
代码的简化版本
const _ = require('lodash');
const test = (name) => {
return new Promise(function(resolve, reject) {
//This is simplified from my actual code
resolve(name);
});
};
const testAll = (arr) => {
//This chains and returns a series of functions with the order of arr, so that the can be executed in the order, not simultaneously
let functions = _.map(arr, element => test.bind(null, element));
//This reduces the functions and is supposed to return an array of all values
return functions.reduce((fun1, fun2) => fun1.then(fun2), Promise.resolve([]));
}
const arr = ['promise1', 'promise2', 'promise3'];
testAll(arr)
.then(data => console.log(data));
我期待输出(带订单):
promise1
promise2
promise3
但我真正得到的只是承诺3.是因为Promise.resolve([])不包含数组中的每个元素吗?
解决方法:
您似乎希望将单个结果累积到数组中.为此,您必须至少从每个承诺中捕获已解决的值.当你做fun1.then(fun2)时,你扔掉了fun1承诺的价值.要使用它,您需要对传递给then回调的参数执行某些操作.在您的情况下,您希望将其与fun2()的承诺值连接起来.
但既然你有第一个,但仍然必须等待第二个,你可以从Promise.all中受益,像这样:
const testAll = (arr) => {
let functions = arr.map(element => test.bind(null, element));
return functions.reduce((prom, fun) =>
prom.then(data => Promise.all(data.concat(fun())) ),
Promise.resolve([])
);
}
现在,您对testAll的最终调用将为您提供一个数组作为结果.
const test = (name) => {
return new Promise(function(resolve, reject) {
setTimeout(_ => { // Introduce delay for better demo
console.log('.'); // a little trace in the output
resolve(name);
}, 500);
});
};
const testAll = (arr) => {
let functions = arr.map(element => test.bind(null, element));
return functions.reduce((prom, fun) =>
prom.then(data => Promise.all(data.concat(fun())) ),
Promise.resolve([])
);
}
const arr = ['promise1', 'promise2', 'promise3'];
testAll(arr).then(data => console.log(data));