Victor Marchuk
Victor Marchuk

Reputation: 13884

Make async/await loop execute in order

I have a loop that looks like that:

    newThreadIds.map(async function(id) {
      let thread = await API.getThread(id);
      await ActiveThread.findOneAndUpdate({number: id}, {posts: thread.posts}, {upsert: true}).exec();
      await Q.delay(1000);
    });

The problem is that each iteration executes asynchronously and I would like there to be a 1 second delay between them. I know how to do it with promises, but it looks ugly and I would prefer to do it with async/await and as little nesting as possible.

Upvotes: 2

Views: 5530

Answers (2)

Bergi
Bergi

Reputation: 665130

The map function doesn't know that its callback is asynchronous and returns a promise. It just runs through the array immediately and creates an array of promises. You would use it like

const promises = newThreadIds.map(async function(id) {
    const thread = await API.getThread(id);
    return ActiveThread.findOneAndUpdate({number: id}, {posts: thread.posts}, {upsert: true}).exec();
});
const results = await Promise.all(promises);
await Q.delay(1000);

For sequential execution, you would need to use Bluebird's mapSeries function (or something similar from your respective library) instead, which cares about the promise return values of each iteration.

In pure ES6, you'd have to use an actual loop, whose control flow will respect the await keyword in the loop body:

let results = [];
for (const id of newThreadIds) {
    const thread = await API.getThread(id);
    results.push(await ActiveThread.findOneAndUpdate({number: id}, {posts: thread.posts}, {upsert: true}).exec());
    await Q.delay(1000);
}

Upvotes: 7

Victor Marchuk
Victor Marchuk

Reputation: 13884

I've figured it out:

    for (let id of newThreadIds) {
      let thread = await API.getThread(id);
      await ActiveThread.findOneAndUpdate({number: id}, {posts: thread.posts}, {upsert: true}).exec();
      await Q.delay(1000);
    }

It's probably the best way to it with ES2015 and async/await.

Upvotes: 6

Related Questions