Reputation: 13884
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
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
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