Promise.allSettled() is a Promise static method introduced in ES2020 that allows us to wait for all Promises to complete (whether successful or failed) and returns the status and result of each Promise.
Basic Concept
Promise.allSettled() accepts an array of Promises as a parameter and returns a new Promise. This new Promise will complete only after all input Promises have completed (whether successful or failed), returning an array containing the status and result of each Promise.
Basic Usage
javascriptconst promise1 = Promise.resolve(42); const promise2 = Promise.reject('Error occurred'); const promise3 = new Promise(resolve => setTimeout(() => resolve('Delayed completion'), 1000)); Promise.allSettled([promise1, promise2, promise3]) .then(results => { console.log(results); // Output: // [ // { status: 'fulfilled', value: 42 }, // { status: 'rejected', reason: 'Error occurred' }, // { status: 'fulfilled', value: 'Delayed completion' } // ] });
Return Value Structure
Each result object contains two properties:
status: 'fulfilled' (success) or 'rejected' (failure)value: The value on success (only exists when status is 'fulfilled')reason: The reason on failure (only exists when status is 'rejected')
Comparison with Promise.all()
Promise.all() - Fast Fail
javascriptconst promise1 = Promise.resolve(1); const promise2 = Promise.reject('Error'); const promise3 = Promise.resolve(3); Promise.all([promise1, promise2, promise3]) .then(results => console.log(results)) .catch(error => console.error('Error:', error)); // Output: Error: Error // The result of promise3 cannot be obtained
Promise.allSettled() - Wait for All
javascriptconst promise1 = Promise.resolve(1); const promise2 = Promise.reject('Error'); const promise3 = Promise.resolve(3); Promise.allSettled([promise1, promise2, promise3]) .then(results => { results.forEach(result => { if (result.status === 'fulfilled') { console.log('Success:', result.value); } else { console.error('Failure:', result.reason); } }); }); // Output: // Success: 1 // Failure: Error // Success: 3
Practical Use Cases
1. Batch Requests, Partial Failures Don't Affect Other Results
javascriptasync function fetchMultipleUrls(urls) { const promises = urls.map(url => fetch(url).then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); }) ); const results = await Promise.allSettled(promises); const successful = results .filter(result => result.status === 'fulfilled') .map(result => result.value); const failed = results .filter(result => result.status === 'rejected') .map(result => result.reason); console.log('Successful requests:', successful.length); console.log('Failed requests:', failed.length); return { successful, failed }; } // Usage example const urls = [ 'https://api.example.com/users', 'https://api.example.com/posts', 'https://api.example.com/comments' ]; fetchMultipleUrls(urls).then(({ successful, failed }) => { console.log('Successful data:', successful); console.log('Failed reasons:', failed); });
2. Process Multiple Tasks in Parallel, Collect All Results
javascriptasync function processTasks(tasks) { const results = await Promise.allSettled( tasks.map(task => task()) ); return results.map((result, index) => ({ task: tasks[index].name, status: result.status, result: result.status === 'fulfilled' ? result.value : result.reason })); } // Usage example const tasks = [ { name: 'Task 1', fn: () => Promise.resolve('Completed') }, { name: 'Task 2', fn: () => Promise.reject('Failed') }, { name: 'Task 3', fn: () => Promise.resolve('Completed') } ]; processTasks(tasks).then(results => { console.table(results); });
3. Image Loading, Display Successful and Failed Images
javascriptasync function loadImages(imageUrls) { const imagePromises = imageUrls.map(url => { return new Promise((resolve, reject) => { const img = new Image(); img.onload = () => resolve({ url, img }); img.onerror = () => reject(new Error(`Failed to load: ${url}`)); img.src = url; }); }); const results = await Promise.allSettled(imagePromises); const loadedImages = results .filter(result => result.status === 'fulfilled') .map(result => result.value); const failedUrls = results .filter(result => result.status === 'rejected') .map(result => result.reason.message); return { loadedImages, failedUrls }; } // Usage example const imageUrls = [ 'https://example.com/image1.jpg', 'https://example.com/image2.jpg', 'https://example.com/image3.jpg' ]; loadImages(imageUrls).then(({ loadedImages, failedUrls }) => { console.log('Successfully loaded images:', loadedImages); console.log('Failed to load images:', failedUrls); });
Error Handling
Handling Partial Failures
javascriptasync function fetchWithPartialFailure(urls) { const results = await Promise.allSettled( urls.map(url => fetch(url)) ); const successfulRequests = results .filter(result => result.status === 'fulfilled') .map(result => result.value); const failedRequests = results .filter(result => result.status === 'rejected') .map(result => result.reason); if (failedRequests.length > 0) { console.warn('Some requests failed:', failedRequests); } return successfulRequests; }
Retrying Failed Requests
javascriptasync function fetchWithRetry(urls, maxRetries = 3) { const results = await Promise.allSettled( urls.map(url => fetch(url)) ); const failedUrls = results .filter(result => result.status === 'rejected') .map((result, index) => urls[index]); if (failedUrls.length > 0) { console.log(`Retrying failed requests (${maxRetries} times)`); const retryResults = await Promise.allSettled( failedUrls.map(url => fetch(url)) ); // Handle retry results... } return results; }
Performance Considerations
1. Empty Array Handling
javascriptPromise.allSettled([]) .then(results => console.log(results)); // Output: []
2. Non-Promise Value Handling
javascriptPromise.allSettled([1, 2, Promise.resolve(3)]) .then(results => console.log(results)); // Output: // [ // { status: 'fulfilled', value: 1 }, // { status: 'fulfilled', value: 2 }, // { status: 'fulfilled', value: 3 } // ]
Comparison with Other Promise Methods
| Method | Behavior | Use Case |
|---|---|---|
| Promise.all() | All succeed or all fail | Need all results to succeed |
| Promise.allSettled() | Wait for all to complete, return all results | Need to know result of each operation |
| Promise.race() | Return first completed result | Need fastest result |
| Promise.any() | Return first successful result | Need any successful result |
Best Practices
1. Check All Results
javascriptasync function checkAllResults(promises) { const results = await Promise.allSettled(promises); const hasFailures = results.some(result => result.status === 'rejected'); if (hasFailures) { const failures = results .filter(result => result.status === 'rejected') .map(result => result.reason); console.error('Some operations failed:', failures); } return results; }
2. Aggregate Results
javascriptasync function aggregateResults(promises) { const results = await Promise.allSettled(promises); return { total: results.length, successful: results.filter(r => r.status === 'fulfilled').length, failed: results.filter(r => r.status === 'rejected').length, results: results }; }
3. Provide Fallback
javascriptasync function fetchWithFallback(urls, fallbackData) { const results = await Promise.allSettled( urls.map(url => fetch(url).then(r => r.json())) ); const data = results.map((result, index) => { if (result.status === 'fulfilled') { return result.value; } else { console.warn(`Request ${urls[index]} failed, using fallback data`); return fallbackData[index]; } }); return data; }
Browser Compatibility
Promise.allSettled() was introduced in ES2020 and is supported by modern browsers:
- Chrome: 76+
- Firefox: 71+
- Safari: 13+
- Edge: 79+
For older browsers, you can use a polyfill:
javascriptif (!Promise.allSettled) { Promise.allSettled = function(promises) { return Promise.all( promises.map(promise => Promise.resolve(promise).then( value => ({ status: 'fulfilled', value }), reason => ({ status: 'rejected', reason }) ) ) ); }; }
Summary
- Wait for all Promises to complete: Waits for all Promises to complete whether successful or failed
- Return detailed results: Returns the status and result of each Promise
- Suitable for partial failure scenarios: Use when some operations failing doesn't affect others
- Complementary to Promise.all(): Promise.all() fails fast, Promise.allSettled() waits for all
- Better error handling: Can handle each failed operation individually
- Polyfill support: Can be implemented with polyfill for older browsers