JavaScript array .reduce with async/await

似乎在将 async/await 与 .reduce() 合并时遇到了一些问题,如下所示:

const data = await bodies.reduce(async(accum, current, index) => {
  const methodName = methods[index]
  const method = this[methodName]
  if (methodName == 'foo') {
    current.cover = await this.store(current.cover, id)
    console.log(current)
    return {
      ...accum,
      ...current
    }
  }
  return {
    ...accum,
    ...method(current.data)
  }
}, {})
console.log(data)

在完成之前记录该对象...datathis.store

我知道你可以使用异步循环,但这适用于吗?Promise.all.reduce()


答案 1

问题是你的累加器值是承诺 - 它们是s的返回值。要获得顺序评估(以及等待的最后一次迭代之外的所有迭代),您需要使用async function

const data = await array.reduce(async (accumP, current, index) => {
  const accum = await accumP;
  …
}, Promise.resolve(…));

也就是说,对于/我通常建议使用普通循环而不是数组迭代方法,它们的性能更高,而且通常更简单。asyncawait


答案 2

我喜欢Bergi的答案,我认为这是正确的方法。

我还想提一下我的一个图书馆,叫做Respecty.js

这使您可以毫不费力地使用诸如 , & 具有以下功能:reducemapfilterasync / await

import reduce from 'awaity/reduce';

const posts = await reduce([1,2,3], async (posts, id) => {

  const res = await fetch('/api/posts/' + id);
  const post = await res.json();

  return {
    ...posts,
    [id]: post
  };
}, {})

posts // { 1: { ... }, 2: { ... }, 3: { ... } }