如何在 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);