Improve API Fault Tolerance with Promise.allSettled
Concurrent API fetching is a standard requirement in modern web
applications, but network instability and failing third-party services
can easily disrupt data aggregation. While traditional approaches like
Promise.all immediately fail if even a single request is
rejected, JavaScript's Promise.allSettled ensures all
asynchronous operations run to completion regardless of their individual
outcomes. This article explains how Promise.allSettled
enhances fault tolerance by preventing single points of failure,
enabling graceful UI degradation, and simplifying error recovery when
fetching data from multiple endpoints simultaneously.
The Limitation of Traditional Concurrent Fetching
When coordinating multiple network requests simultaneously,
developers often turn to Promise.all. However,
Promise.all implements a "fail-fast" mechanism: if any
single promise rejects, the entire aggregate promise immediately
rejects.
In a scenario where an application requests user profile data,
notification counts, and analytics metrics concurrently, an outage in
the analytics service will cause Promise.all to drop the
entire payload. The application loses access to the valid, successfully
returned user profile and notification data, leaving the user with an
empty screen or an unnecessary fatal error state.
How Promise.allSettled Enhances Fault Tolerance
Introduced in ECMAScript 2020, Promise.allSettled
accepts an iterable of promises and resolves only after all the given
promises have either fulfilled or rejected. Unlike
Promise.all, it never short-circuits on failure.
Instead of returning a single aggregated array of results or throwing
a single error, Promise.allSettled resolves to an array of
outcome objects. Each object describes the result of each individual
promise:
- Fulfilled promises return
{ status: 'fulfilled', value: data } - Rejected promises return
{ status: 'rejected', reason: error }
This shift in execution provides three primary architectural benefits for fault tolerance:
1. Graceful Degradation of User Interfaces
Modern web interfaces often resemble dashboards composed of discrete
widgets or independent modules. By using
Promise.allSettled, an application can inspect each result
independently. If the API providing promotional banners fails, the
application can safely render the core content, product listings, and
navigation items while displaying an unobtrusive fallback state or
placeholder for the failed banner.
2. Comprehensive Error Logging and Auditing
Under the Promise.all model, only the first rejection is
caught; all subsequent failures are ignored or swallowed.
Promise.allSettled preserves the outcome of every request
in the batch. This allows monitoring tools to log the exact set of
failing endpoints across a single user interaction, providing clear
insights into systemic service degradations versus isolated client-side
errors.
3. Simplified Partial-Success Handling
Handling partial successes with Promise.all typically
requires wrapping every individual fetch call in a custom
.catch() handler to normalize rejections into resolved
values. Promise.allSettled standardizes this behavior
natively. Developers can process the final array using standard array
methods to separate successes from failures:
const results = await Promise.allSettled([
fetchUserData(),
fetchNotifications(),
fetchAnalytics()
]);
const successfulData = results
.filter((res) => res.status === 'fulfilled')
.map((res) => res.value);
const errors = results
.filter((res) => res.status === 'rejected')
.map((res) => res.reason);Ideal Use Cases
Promise.allSettled is best suited for non-dependent
concurrent tasks where partial data is preferable to no data:
- Composite Dashboards: Pages pulling data from multiple independent microservices.
- Batch Operations: Submitting multiple forms, sending bulk emails, or uploading several files where failures should be flagged individually without halting the rest of the queue.
- Health Checks and Monitoring: Pinging multiple third-party integrations to report on overall service health.
By preventing isolated network issues from invalidating an entire
batch of requests, Promise.allSettled provides a robust,
native foundation for resilient data-fetching strategies in distributed
web environments.