How to make three API calls finish in the time it takes to make one.
Sponsor this newsletter · reach 9,500+ active developers
You need a user, their posts, and their followers. So you fetch the user, wait, fetch the posts, wait, fetch the followers, wait. Three seconds of waiting in a row when one second was possible. Promise.all runs all three requests at the same time and waits for all of them together. The total wait is the slowest request, not the sum of all requests.
The slow way vs the fast way
// slow: sequential - 3 seconds total
const user = await fetchUser(id); // 1s
const posts = await fetchPosts(id); // 1s
const followers = await fetchFollowers(id); // 1s
// fast: parallel - ~1 second total
const [user, posts, followers] = await Promise.all([
fetchUser(id),
fetchPosts(id),
fetchFollowers(id),
]);
The results come back in the same order as the array, so destructuring works perfectly. If any one of the promises rejects, the whole Promise.all rejects immediately.
When one failure should not stop the rest
Sometimes a failed secondary request should not break the whole page. Use Promise.allSettled instead. It waits for every promise to finish regardless of success or failure, and gives you the result of each:
const results = await Promise.allSettled([
fetchUser(id),
fetchPosts(id),
fetchFollowers(id),
]);
results.forEach(result => {
if (result.status === 'fulfilled') {
console.log(result.value);
} else {
console.warn('Failed:', result.reason);
}
});
A profile page that still shows the user and their posts even when the followers count fails to load is a much better experience than a full page error.
Why it matters
- Faster pages, same code. Wrapping three existing fetch calls in
Promise.allcan cut load time by 60% or more with almost no refactoring. - Cleaner than chaining. No nested
.then()chains, no intermediate variables to pass down. One line, all results. - All browsers.
Promise.allis Baseline 2015.Promise.allSettledis Baseline 2020. Both available everywhere without a polyfill.
Any time you see two or more await calls in a row that do not depend on each other, that is a candidate for Promise.all. It is one of the highest-return refactors you can make to an existing async codebase.
Just a reminder you can use Snippet Editor for your code snippets.
Happy coding!
Marko