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()