How to run several async operations in parallel
Short answer
Promise.all() starts waiting for all promises at once and returns an array of results in the same order:
const delay = (ms, value) => new Promise((resolve) => setTimeout(() => resolve(value), ms));
const start = Date.now();
const [user, orders] = await Promise.all([delay(300, 'Anna'), delay(300, 3)]);
console.log(user, orders);
console.log(Date.now() - start < 500 ? 'about 300 ms, not 600' : 'slow');Output:
Anna 3
about 300 ms, not 600With fetch
The same with requests: both start at once:
const [user, orders] = await Promise.all([
fetch('/api/user').then((r) => r.json()),
fetch('/api/orders').then((r) => r.json()),
]);When some may fail
Promise.all() fails as soon as one promise fails. Promise.allSettled() waits for all and reports the status of each:
const results = await Promise.allSettled([
Promise.resolve('photo 1'),
Promise.reject(new Error('photo 2 is too large')),
Promise.resolve('photo 3'),
]);
for (const result of results) {
console.log(result.status, result.value ?? result.reason.message);
}Output:
fulfilled photo 1
rejected photo 2 is too large
fulfilled photo 3Common mistake
await in a loop runs the operations one by one. If they do not depend on each other, that is just slower:
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const start = Date.now();
for (const ms of [200, 200, 200]) {
await delay(ms);
}
console.log(Date.now() - start >= 600 ? 'one by one: 600 ms' : 'fast');Output:
one by one: 600 msFunctions used in this recipe
- Promise.all — Waits for all promises in parallel.
- Promise.allSettled — Waits for every promise to settle and reports each result — success or failure.