What they're testing
Whether you think about the failure path or only the happy path.
The short answer~30 seconds
all rejects the moment one fails — use it when a missing piece makes the whole result meaningless. allSettled always resolves with per-item status — use it for dashboards, where three working widgets should render. race settles with the first outcome, success or failure — that's your timeout. any takes the first success and ignores failures — use it with redundant sources.
The long answer
The most important thing none of the four do: they don't cancel the remaining promises. A rejecting Promise.all doesn't stop the other three requests — they keep running, keep consuming bandwidth, and if they also reject you get unhandled rejections. Real cancellation means an AbortController with its signal passed into each fetch.
The second trap is that a promise starts running when it's CREATED, not when it's awaited. So await Promise.all([a(), b()]) runs them in parallel while const x = await a(); const y = await b(); runs them in series — two lines that look alike and take twice as long. Conversely, creating 5,000 promises at once and calling Promise.all is the fastest way to take down your own server; that calls for a concurrency-limited pool.
race has a detail people get wrong as a timeout: if the losing branch is a setTimeout, that timer stays alive until it fires. Across a few thousand requests that's a few thousand dangling timers. AbortSignal.timeout() is the better choice where available, because it cancels the request rather than merely ignoring its result.
// Dashboard: một widget hỏng không được làm trắng cả trang
const results = await Promise.allSettled([users(), orders(), alerts()]);
const widgets = results.map((r) =>
r.status === 'fulfilled' ? render(r.value) : renderError(r.reason),
);
// Timeout có huỷ thật, không để timer treo
const res = await fetch(url, { signal: AbortSignal.timeout(3000) });
// Tuần tự (chậm gấp đôi) so với song song
const a = await first(); const b = await second(); // 2 × latency
const [a, b] = await Promise.all([first(), second()]); // 1 × latencyWhat they'll ask next
?How do you cap concurrency at 10?
A pool: keep at most ten in flight and start the next as each settles. p-limit and friends do it for you. The part worth stating is WHY: the receiving side's rate limit, or your own database pool.
?Does Promise.all preserve result order?
Yes — the result array follows the input order regardless of completion order. That's an important difference from collecting results yourself in a for await loop.
These lose points
- Assuming a rejecting
Promise.allstops the others. It doesn't, and that's a real source of unhandled rejections. - Using
Promise.allover an unbounded list. Ten thousand simultaneous requests is a self-inflicted attack.