异步/等待内部减少

时间:2020-01-08 16:04:45

标签: javascript async-await reduce

我正在尝试将async / awaitreduce方法一起使用。但是以某种方式,只有循环的第一次迭代有效。一旦完成第一次await迭代,papers对象将跳过reduce。是否可以使用reduce创建对象,同时从承诺中收集内容,同时还要等待整个过程?

缩小功能:

const papers = await page.concepts.reduce(async (acc, cur) => {
  acc[cur.paperID] = await getPageData(`papers/${ cur.paperID }`, 'md')
  return acc
}, {})

注意:getPageData返回一个承诺。

3 个答案:

答案 0 :(得分:2)

您可以创建一个承诺数组,然后使用Promise.all来解决它们。如果任何请求失败,Promise.all将停止处理其余请求。

const papersPromises = page.concepts.map(cur => 
    getPageData(`papers/${ cur.paperID }`, 'md')
)

const result = await Promise.all(papersPromises)
// result will be an array with the results

答案 1 :(得分:1)

这是将数组折叠到对象中的一种方法,但是自然地,它不会处理异步函数并减少自身。另外,reduce不会返回Promise来等待

您可以使用Promise.allObject.fromEntries

解决您的情况
// map concepts to promises which will resolve to page data for each concept
// and await for them all at once (will run in parallel)
const pageResponses = await Promise.all(page.concepts.map(concept => getPageData(`papers/${concept.paperID}`, 'md')))
// construct object where keys are concept.paperIDs and values are pageDatas
const papers = Object.fromEntries(
  page.concepts
    .map((concept, i) => ([concept.paperID, pageResponses[i]]))
)

如果您的运行时不支持Object.fromEntries(并且您没有使用polyfill),则可以执行最后一部分

const papers = page.concepts.reduce((acc, concept, index) => acc[concept.paperID] = pageResponses[index], {})

答案 2 :(得分:1)

由于异步函数返回了一个Promise,因此您必须期望累加器是一个Promise。因此,您将执行以下操作:

console.log("Program starting at", Date());

function delayedResolver(a, ms) {
    return new Promise(function(resolve, reject) {
        setTimeout(() => {
            console.log("resolving at", Date());
            resolve(a);
        }, ms);
    });
}

arr = [1, 3, 5];

r = arr.reduce(async function(a, b) { 
      return await delayedResolver(a, 3000).then(v => v + b); 
    }, Promise.resolve(0));

console.log(r);

r.then(v => console.log("final value", v, "at", Date()));

您必须将累加器视为一个承诺,并每次都返回一个新的承诺。

请注意,异步函数返回一个诺言,而reduce立即将异步函数应用于下一对(accumulator, entry),因此异步函数返回的所有这些诺言几乎都是立即创建的,因此为什么承诺会在3秒后全部解决,而不是一一解决。