How to wait for a promise within a loop block

JavaScript promises enable developers to write asynchronous applications in JavaScript

Loops are ways of iterating elements
For instance doing an asynchronous task within a for loop can be done as follows;
Note that lag is used to emulate some delay.

const items = [1, 2, 3, 4]
const lag = async (delay) => {
    return new Promise((resolve) =>
        setTimeout(() => res(`${delay / 1000} sec`), delay))
}

items.forEach(async (item) => {
    const seconds = await lag(1000 * item)
    console.log(seconds)
})

expected output

1 sec
2 sec
3 sec
4 sec

After running the code above every second some text was printed

Comments

  1. This won't work as expected. Try adding a console.log after the forEach call. It will log before all other lag calls resolve. This is in most cases not indented.
    This should do the job:

    const allPromises = await Promise.all(items.map(async i => {
    await lag(i * 1000);
    console.log(i + " sec");
    }));
    console.log("done");

    This code will execute all async functions in parallel and waits until the last Promise resolves.
    If you want to wait for the previous Promise to resolve before starting the next one, switch the Array.map function with reduce, and await the accumulator Promise.

    ReplyDelete
  2. I really like your blog! Keep learning in public. With your pace of learning new things you will achieve your goals in no time 👍🏻💪🏻

    ReplyDelete
  3. Tim, promise all is a good alternative too.

    ReplyDelete
  4. I created a CodeSandBox to make it more clear what I meant.

    https://codesandbox.io/s/hungry-chaum-ezh7v

    The forEach version looks like it works, but you never know, when all Promises are done. This behavior can lead to nasty bugs.

    ReplyDelete
  5. The CodeSandBox illustration is clear.
    I see the significance of using primise all ,
    especially in a production environment.

    ReplyDelete

Post a Comment