Async/await in foreach not waiting
Use Promise.all
and map
get all inner promises and return a single one that awaits them all:
const addExtrasToDocsForUser = async (docs, currentUserId, events) => {
return Promise.all(docs.map(async (eventDoc) => {
const event = await addExtrasToDocForUser(eventDoc, currentUserId)
events.push(event)
}));
}
Basically, this is what happens inside forEach
:
Array.prototype.forEach = function (callback) {
for (let index = 0; index < this.length; index++) {
callback(this[index], index, this);
}
};
Actually, the real implementation is the following, but the bottom line is that we are not waiting for the callback to be done, so using a function that returns a promise won't wait for the promise to resolve everytime.
Your code is not complete and verifiable so I can't be sure that the following works, but it probably should act as you'd expect:
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;
}
You might also want to check this CodeBurst article on foreach + async/await
Why do you combine synchronous and asynchronous functions?
You call await addExtrasToDocsForUser(docs, currentUserId, events)
, but your function addExtrasToDocsForUser is not async
.
var addExtrasToDocsForUser = async (docs, currentUserId, events) => {
return await docs.forEach(async (eventDoc) => {
const event = await addExtrasToDocForUser(eventDoc, currentUserId)
events.push(event)
})
}
You want to do something like this:
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()