How to run async operations one after another
Short answer
await inside a for...of loop waits for each operation before starting the next one:
const delay = (ms, value) => new Promise((resolve) => setTimeout(() => resolve(value), ms));
for (const file of ['a.txt', 'b.txt', 'c.txt']) {
const result = await delay(100, `uploaded ${file}`);
console.log(result);
}Output:
uploaded a.txt
uploaded b.txt
uploaded c.txtEach step uses the previous result
When steps depend on each other, just write them one after another:
const getUser = async (id) => ({ id, name: 'Anna' });
const getOrders = async (user) => [`order of ${user.name}`];
const user = await getUser(1);
const orders = await getOrders(user);
console.log(orders[0]);Output:
order of AnnaCollecting results
Push each result into an array:
const double = async (n) => n * 2;
const results = [];
for (const n of [1, 2, 3]) {
results.push(await double(n));
}
console.log(results.join(', '));Output:
2, 4, 6Common mistake
forEach() does not wait for async functions. The code after it runs before the steps finish:
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
[1, 2].forEach(async (n) => {
await delay(100);
console.log('step', n);
});
console.log('done?');Output:
done?
step 1
step 2Functions used in this recipe
- async function — A function that always returns a promise and lets you use await inside.
- Array.prototype.reduce — Reduces an array to a single value.