Intermediate · Asynchronous JavaScript · topic 39 of 61 · 25 min
Promise.all, allSettled, race and any
Explanation
Why combine promises?
Real apps often run several async tasks: load five widgets, send 100 SMS, ask three servers for the fastest answer. The Promise class has four static methods for these patterns. Each takes an iterable of promises and returns ONE promise.
| Method | Fulfils when | Rejects when | Use for |
|---|---|---|---|
| Promise.all | all fulfil (array of values, in input order) | any one rejects (fail fast) | Everything is needed |
| Promise.allSettled | all settle (never rejects) | — | Report each success/failure |
| Promise.race | the first to settle fulfils | the first to settle rejects | Timeouts |
| Promise.any | the first to fulfil | all reject (AggregateError) | Fastest working mirror |
Promise.all
const [user, orders] = await Promise.all([getUser(7), getOrders(7)]);
// results come in INPUT order, not finishing orderIf one promise rejects, Promise.all rejects immediately with that error. The other operations keep running in the background (promises cannot be cancelled), but their results are ignored.
Promise.allSettled
const results = await Promise.allSettled([sendSms('A'), sendSms('B'), sendSms('C')]);
// [{ status: 'fulfilled', value: … }, { status: 'rejected', reason: Error }, …]
const failed = results.filter((r) => r.status === 'rejected').length;
console.log(`${failed} SMS failed`);Timeouts with race
function withTimeout(promise, ms) {
const timeout = new Promise((_, reject) =>
setTimeout(() => reject(new Error(`Timed out after ${ms} ms`)), ms)
);
return Promise.race([promise, timeout]);
}
// await withTimeout(fetchFare(), 3000);Retry with backoff
Networks fail now and then. A retry tries again a few times, waiting a little longer each time (backoff), so a struggling server is not flooded.
async function retry(task, attempts = 3, delayMs = 200) {
for (let i = 1; i <= attempts; i++) {
try {
return await task();
} catch (err) {
if (i === attempts) throw err;
await new Promise((r) => setTimeout(r, delayMs * 2 ** (i - 1))); // 200, 400, 800…
}
}
}Limiting concurrency
Promise.all on 10,000 requests starts them all at once, which can overload a server or hit rate limits. A small pool runs at most N at a time.
async function mapWithLimit(items, limit, worker) {
const results = new Array(items.length);
let next = 0;
async function runner() {
while (next < items.length) {
const i = next++;
results[i] = await worker(items[i]);
}
}
await Promise.all(Array.from({ length: Math.min(limit, items.length) }, runner));
return results;
}Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Promise.all, allSettled, race and any · 1/6
In this lesson you will combine many promises with four helpers.
Prefer a video by a teacher? Find free videos on “javascript promise.all allSettled race any explained” on YouTube ↗
In real life: Sending festival offers by SMS
A retail chain sends a Diwali offer to 20,000 customers through an SMS provider that allows 10 requests at a time. The team uses a concurrency limit of 10, retries each failed send twice, and uses allSettled-style reporting to list the numbers that still failed for a later attempt.
const sendSms = async (n) => { if (n.endsWith('3')) throw new Error('bad number'); return 'ok'; };
const numbers = ['9811111111', '9822222223', '9833333333'];
Promise.allSettled(numbers.map(sendSms)).then((res) => {
const failed = numbers.filter((_, i) => res[i].status === 'rejected');
console.log(failed); // ['9822222223', '9833333333']
});Practice (0/3 done)
Write withTimeout(promise, ms) that returns a promise which settles like the given promise, but rejects with an Error "Timed out" if it takes longer than ms.
Write summarise(tasks) where tasks is an array of functions returning promises. Run them all and return { ok, failed } counts, never rejecting. Use Promise.allSettled.
Write retry(task, attempts) that calls the async function task up to attempts times until it succeeds, returning its value. If every attempt fails, reject with the LAST error. (No delay needed.)
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- The event loopAsynchronous JavaScript · same module
- async/await and error handlingFrontend Web Development · Async JavaScript, modules and tools
- Loading, errors and slow networksFull-Stack Development · Connecting frontend and backend
- Promises and the event loopFrontend Web Development · Async JavaScript, modules and tools
- Concurrency 1: threads, mutexes and data racesC++ Programming (modern C++ and DSA) · Exceptions, concurrency and building projects with CMake
- Resilience patterns, capacity and chaos engineeringDevOps: Git, Docker, Kubernetes and CI/CD · SRE: reliability and incidents
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
Promise.all([p1, p2]) where p2 rejects. What happens?
Answer: It rejects with p2's error
Promise.all fails fast on the first rejection.
Which never rejects?
Answer: Promise.allSettled
allSettled always fulfils with a report for each promise.
In what order does Promise.all return values?
Answer: Input order
Results match the order of the input promises.
Why can retrying a payment be dangerous?
Answer: The first attempt may have succeeded, causing a double charge
Only retry idempotent operations, or use idempotency keys.
Three independent requests each take about 1 second. How long does await Promise.all([a(), b(), c()]) take?Related
Answer: About 1 second
Promise.all starts them together, so the total is about the slowest one. Awaiting them one by one would take about 3 seconds.
Promise.resolve(2).then((n) => n * 3).then((n) => n + 1) fulfils with…Related
Which request is safe to retry automatically after a network error?Related
Answer: GET /api/notes
Reading notes again changes nothing. A POST may already have worked, so repeating it can create duplicates or double payments.
How do you handle a rejected await?Related
Answer: try/catch around the await
A rejection is thrown at the await, so catch it.
From async and await
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 2 more topics in “Asynchronous JavaScript” before its exam: The event loop, fetch: talking to servers.
- Module 8 exam: Asynchronous JavaScript · 12 questions · 25 min, without help. 6 topics of this module still to finish first.
- Then the next module, TypeScript basics. 61 topics left in the course before the final exam.