如何在 Promise.all 中使用 reduce 而不是 map
How to use reduce in a Promise.all instead of map
如何在使用 Promise.all 时使用 reduce 代替 map?我的尝试导致错误 UnhandledPromiseRejectionWarning: TypeError: #<Promise> is not iterable at Function.all (<anonymous>)
最终我想有条件地将 innerResult 添加到 memo 但我需要先使用 reduce。
const _ = require('lodash');
const eq = [{id:1}, {id:2}, {id:3}];
// block to replace
var biggerEq = _.map(eq, async (e) => {
const innerResult = await wait(e.id);
return innerResult;
})
// attempt at replacing above block
// var biggerEq = _.reduce(eq, async (memo, e) => {
// const innerResult = await wait(e.id);
// memo.push(innerResult)
// return memo;
// }, []);
Promise.all(biggerEq).then((result) => {
console.log(result) // outputs [ 2, 4, 6 ]
})
function wait (id) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(id * 2);
}, 1000);
})
}
如果想换成reduce
是可以的,但是逻辑会有点绕。使累加器成为一个 Promise,它解析为一个数组,您可以 push
到,然后 return 它以便下一次迭代可以使用它(作为 Promise):
const eq = [{id:1}, {id:2}, {id:3}];
function wait (id) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(id * 2);
}, 1000);
})
}
const biggerEq = _.reduce(eq, async (arrProm, obj) => {
const [arr, innerResult] = await Promise.all([arrProm, wait(obj.id)]);
arr.push(innerResult);
return arr;
}, Promise.resolve([]));
biggerEq.then((arr) => {
console.log(arr);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
(但是当你想将一个数组转换成另一个数组时,.map
确实更合适)
我认为某些性能过于复杂了。您可以像这样使用 Promise.all:
const eq = [{id: 1}, {id: 2}, {id: 3}];
function wait(id) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(id * 2);
}, 1000);
});
}
const biggerEq = _.reduce(eq, (arr, obj) => {
const p = wait(obj.id);
arr.push(p);
return arr;
}, []);
Promise.all(biggerEq).then((arr) => {
console.log(arr);
});
请注意,问题在于在 reduce 中使用 await
。这意味着您将承诺的结果推入数组,而不是获得承诺的数组。使用该方法,您 已经在数组中得到了结果 ,因此不需要 Promise.all
,但是有一个很大的缺点,即 promises 是连续解析的。如果那确实是您想要的,您可以:
const results = _.reduce(eq, async (arr, obj) => {
const p = await wait(obj.id);
arr.push(p);
return arr;
}, []);
console.log(results);
如何在使用 Promise.all 时使用 reduce 代替 map?我的尝试导致错误 UnhandledPromiseRejectionWarning: TypeError: #<Promise> is not iterable at Function.all (<anonymous>)
最终我想有条件地将 innerResult 添加到 memo 但我需要先使用 reduce。
const _ = require('lodash');
const eq = [{id:1}, {id:2}, {id:3}];
// block to replace
var biggerEq = _.map(eq, async (e) => {
const innerResult = await wait(e.id);
return innerResult;
})
// attempt at replacing above block
// var biggerEq = _.reduce(eq, async (memo, e) => {
// const innerResult = await wait(e.id);
// memo.push(innerResult)
// return memo;
// }, []);
Promise.all(biggerEq).then((result) => {
console.log(result) // outputs [ 2, 4, 6 ]
})
function wait (id) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(id * 2);
}, 1000);
})
}
如果想换成reduce
是可以的,但是逻辑会有点绕。使累加器成为一个 Promise,它解析为一个数组,您可以 push
到,然后 return 它以便下一次迭代可以使用它(作为 Promise):
const eq = [{id:1}, {id:2}, {id:3}];
function wait (id) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(id * 2);
}, 1000);
})
}
const biggerEq = _.reduce(eq, async (arrProm, obj) => {
const [arr, innerResult] = await Promise.all([arrProm, wait(obj.id)]);
arr.push(innerResult);
return arr;
}, Promise.resolve([]));
biggerEq.then((arr) => {
console.log(arr);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
(但是当你想将一个数组转换成另一个数组时,.map
确实更合适)
我认为某些性能过于复杂了。您可以像这样使用 Promise.all:
const eq = [{id: 1}, {id: 2}, {id: 3}];
function wait(id) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(id * 2);
}, 1000);
});
}
const biggerEq = _.reduce(eq, (arr, obj) => {
const p = wait(obj.id);
arr.push(p);
return arr;
}, []);
Promise.all(biggerEq).then((arr) => {
console.log(arr);
});
请注意,问题在于在 reduce 中使用 await
。这意味着您将承诺的结果推入数组,而不是获得承诺的数组。使用该方法,您 已经在数组中得到了结果 ,因此不需要 Promise.all
,但是有一个很大的缺点,即 promises 是连续解析的。如果那确实是您想要的,您可以:
const results = _.reduce(eq, async (arr, obj) => {
const p = await wait(obj.id);
arr.push(p);
return arr;
}, []);
console.log(results);