【问题标题】:await with array foreach containing async await [duplicate]带有包含异步等待的数组 foreach 的等待 [重复]
【发布时间】:2019-01-15 05:54:56
【问题描述】:

在 node.js 中,我需要使用包含 Array.foreach 的 function procesMultipleCandidates (),该过程将每个元素插入到数据库中。但是整个函数应该在完成所有插入操作后返回响应

JavaScript 代码

async function procesMultipleCandidates (data) {
  let generatedResponse = []
  await data.forEach(async (elem) => {
    try {    
          
           // here candidate data is inserted into  
           let insertResponse = await insertionInCandidate(elem) 
           //and response need to be added into final response array 
           generatedResponse.push(insertResponse)
    } catch (error) {
    console.log('error'+ error);
    }
  })
  console.log('complete all') // gets loged first
  return generatedResponse // return without waiting for process of 
}

如上所述,最后一个 return 语句不等待 foreach 执行首先完成。

【问题讨论】:

标签: javascript node.js foreach async-await


【解决方案1】:

请改用Promise.all,这将在传递给它的数组中的所有 Promise 都解析后解析。如果您使用并返回一个普通的Promise 链而不是async/await,则语法可能会被简化:

const procesMultipleCandidates = data => Promise.all(
  data.map(insertionInCandidate)
)
.catch(err => {
  console.log('err: ' + err);
});

请注意,如果出现错误,procesMultipleCandidates 当前将返回已解决的Promise 而不是拒绝 - 让procesMultipleCandidates消费者 处理错误可能是一个更好的主意,所以它可以适当地处理它们(而不是简单地console.logging 它)。

【讨论】:

  • 在您的解决方案中,如何将每个insertionInCandidate() 的响应推送到一个最终响应数组中?
  • .map 正在将data 中的每个项目转换为Promise,该Promise 解析为使用该项目调用insertionInCandidate 的结果 - 将这些Promises 的数组传递给@ 987654336@,Promise.all 将解析为这些值的数组。无需修改代码 - 它非常简洁。
【解决方案2】:

使用Array.prototype.mapPromise.all

async function procesMultipleCandidates (data) {
  let generatedResponse = []
  await Promise.all(data.map(async (elem) => {
    try {
      // here candidate data is inserted into  
      let insertResponse = await insertionInCandidate(elem)  
      // and response need to be added into final response array 
      generatedResponse.push(insertResponse)
    } catch (error) {
      console.log('error'+ error);
    }
  }))
  console.log('complete all') // gets loged first
  return generatedResponse // return without waiting for process of 
}

如果您不希望循环运行 concurrently,请使用 for/of 循环:

async function procesMultipleCandidates (data) {
  let generatedResponse = []
  for(let elem of data) {
    try {
      // here candidate data is inserted into  
      let insertResponse = await insertionInCandidate(elem)  
      // and response need to be added into final response array 
      generatedResponse.push(insertResponse)
    } catch (error) {
      console.log('error'+ error);
    }
  }
  console.log('complete all') // gets loged first
  return generatedResponse // return without waiting for process of 
}

【讨论】:

    【解决方案3】:

    Array.prototype.forEach() 尝试按顺序执行,您可能并不总是得到预期的结果。

    Array.prototype.map() 被广泛用于使用数据创建 Promise,然后使用 await Promise.all([]) 解析

    使用.map()函数,所有的promise都被并行解决,如果你碰巧调用了一个API,你最终可能会得到error 429: Too many Requests

    要按顺序执行所有的 Promise,你可以使用 for ...of

    const array1 = ['a', 'b', 'c'];
    
    for (const element of array1) {
      console.log(element);
    }
    

    MDN Reference

    【讨论】:

      【解决方案4】:

      就我而言,for of 在异步方面的效果比forEach 更好。无论如何,在这种情况下,如果您只关心聚合结果,我认为这可能是一个解决方案。

      async function procesMultipleCandidates(data) {
        const promises = data.map(insertionInCandidate);
        return await Promise.all(promises);
      }
      

      【讨论】:

        猜你喜欢
        • 2019-06-29
        • 2017-01-11
        • 1970-01-01
        • 2019-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-13
        相关资源
        最近更新 更多