提问者:小点点

Async/Await in foreach不等待[重复]


我试图在一个使用循环的函数中使用。令人恼火的是,我不能让它工作。应该发生的情况是,它接受一个事件数组,循环遍历它们,添加一些额外的数据,然后将它们推送到数组。然后从原始函数返回这个数组。下面是我的代码:

async function getEvents() {
  ...
  var events = []
  await addExtrasToDocsForUser(docs, currentUserId, events)
  return events

}


var addExtrasToDocsForUser = (docs, currentUserId, events) => {
    return docs.forEach(async (eventDoc) => {
        const event = await addExtrasToDocForUser(eventDoc, currentUserId)
        events.push(event)
    })
}

实际发生的情况是函数在循环完成之前将作为空数组返回。我该怎么解决这个问题?


共3个答案

匿名用户

为什么要把同步和异步功能结合起来呢?
您调用,但函数addExtrasToDocsForUser不是

var addExtrasToDocsForUser = async (docs, currentUserId, events) => {
  return await docs.forEach(async (eventDoc) => {
    const event = await addExtrasToDocForUser(eventDoc, currentUserId)
    events.push(event)
  })
}

你想做这样的事情:

null

var someOperation = async (op0, op1) => {
	return op0+':'+op1
}

var fnWithForeach = async (docs, number, outputs)=>{
  return await docs.forEach(async (doc)=>{
	const output = await someOperation(doc, number)
	outputs.push(output) 
  })
}

async function getOutputs() {
  // ...
  var docs = ['A', 'B', 'C']
  var number = 10
  // ...
  var outputs = []
  await fnWithForeach(docs, number, outputs)
  return outputs
}

async function main() {
  // ...
  var outputs = await getOutputs()
  console.log(outputs)
  // ...
}

main()

匿名用户

基本上,这就是内部发生的情况:

Array.prototype.forEach = function (callback) {
  for (let index = 0; index < this.length; index++) {
    callback(this[index], index, this);
  }
};

实际上,真正的实现如下所示,但底线是我们并不等待回调完成,因此使用返回承诺的函数不会每次都等待承诺解析。

您的代码并不完整,也不是可验证的,所以我不能确定以下代码是否能正常工作,但它可能会像您所期望的那样工作:

const addExtrasToDocsForUser = async (docs, currentUserId, events) => {
  for (let i=0; i<docs.length; i++) {
    const event = await addExtrasToDocForUser(docs[i], currentUserId);
    events.push(event);
  }
  return;
}

您可能还想查看这篇关于foreach+Async/Await的CodeBurst文章

匿名用户

使用获取所有内部承诺,并返回一个等待它们的单个承诺:

const addExtrasToDocsForUser = async (docs, currentUserId, events) => {
    return Promise.all(docs.map(async (eventDoc) => {
        const event = await addExtrasToDocForUser(eventDoc, currentUserId)
        events.push(event)
    }));
}