Using an async-await call in an asynchronous function inside a forEach method would not work in JavaScript.

Problem

When running the following code, the callback would not return the computed value:

  async function join(name: string, letter: string) {
    return name + letter;
  }

  async function main() {
    const nameLetters = ["s", "h", "a", "r", "o", "o", "q"];
    let name = "";

    nameLetters.forEach(async (letter) => {
      name = await join(name, letter);
    });

    console.log(name); //πŸ‘ˆ This is expected to print "Sharooq"
  }

  main();
not working code

Let's see if we have followed the proper syntax when writing the async-await function.

  1. The main function is wrapped inside an async function.
  2. The callback function of forEach is an async function
  3. The result of the async function is awaited.

So it is evident that the problem is not in the code.

So, Where does the problem lie then?

The problem lies with the way forEach method in JavaScript was implemented. The forEach method was implemented way earlier than when the concept of promise was introduced in JavaScript.

Here is a simplified implementation of forEach method in JavaScript:

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

As you can see, there is no implementation for handling promises in this method. This is why forEach method is not capable of handling awaited callbacks and returns nothing.

Solution

The only solution is to avoid using forEach in the context of an async-await function. You can use any other method to iterate or loop through the array and get the same intended output. For example, let's see an example of the same code with the use of "for" loop.

  async function join(name: string, letter: string) {
    return name + letter;
  }

  async function main() {
    const nameLetters = ["s", "h", "a", "r", "o", "o", "q"];
    let name = "";

    for (let i = 0; i < nameLetters.length; i++) {
      const letter = nameLetters[i];
      name = await join(name, letter);
    }

    console.log(name); //πŸ‘ˆ This will print "Sharooq"
  }

  main();
working code

The above code will output the value "Sharooq" in the console. The only change we made to the code is the use of "for" loop instead of the "forEach" loop.