JavaScript’s Promise handling has evolved significantly over the years, and one of the most powerful additions is the Promise.allSettled() method. Unlike its cousins Promise.all() and Promise.race(), this method offers a unique approach to handling multiple promises simultaneously.
While we’ve covered Promise.all() and Promise.race() in previous articles, Promise.allSettled() deserves special attention for its distinctive ability to handle mixed promise results effectively.
Table of Contents
- What is Promise.allSettled()?
- Syntax
- Return Value Structure
- Basic Usage Example
- Real-World Use Cases
- Error Handling Best Practices
- Browser Compatibility
- Common Pitfalls to Avoid
- When to Use Promise.allSettled()
- Conclusion
What is Promise.allSettled()?
Promise.allSettled() is a method that takes an iterable of promises and returns a new promise that resolves when all input promises have settled (either fulfilled or rejected). The key difference from Promise.all() is that it won’t reject if some promises fail – it waits for all promises to complete regardless of their outcome.
Syntax
Promise.allSettled(iterable)
Code language: JavaScript (javascript)
Return Value Structure
The method returns an array of objects with the following structure:
{
status: 'fulfilled' | 'rejected',
value?: any, // present if status is 'fulfilled'
reason?: any // present if status is 'rejected'
}
Code language: CSS (css)
Basic Usage Example
const promises = [
Promise.resolve(1),
Promise.reject('Error'),
Promise.resolve(3)
];
Promise.allSettled(promises)
.then(results => {
console.log(results);
});
// Output:
// [
// { status: 'fulfilled', value: 1 },
// { status: 'rejected', reason: 'Error' },
// { status: 'fulfilled', value: 3 }
// ]
Code language: JavaScript (javascript)
Real-World Use Cases
1. API Data Fetching
async function fetchUserData(users) {
const userPromises = users.map(user =>
fetch(`https://api.example.com/users/${user}`)
.then(response => response.json())
);
const results = await Promise.allSettled(userPromises);
// Process successful and failed requests separately
const successful = results
.filter(result => result.status === 'fulfilled')
.map(result => result.value);
const failed = results
.filter(result => result.status === 'rejected')
.map(result => result.reason);
return { successful, failed };
}
Code language: JavaScript (javascript)
2. Batch Operations
async function batchProcessFiles(files) {
const operations = files.map(file =>
processFile(file).catch(error => ({
file,
error: error.message
}))
);
const results = await Promise.allSettled(operations);
return results.map(result => {
if (result.status === 'fulfilled') {
return { success: true, data: result.value };
}
return { success: false, error: result.reason };
});
}
Code language: JavaScript (javascript)
Error Handling Best Practices
While Promise.allSettled() doesn’t reject as a whole, it’s still important to handle individual rejections properly:
async function handleBatchOperations(tasks) {
try {
const results = await Promise.allSettled(tasks);
// Process results
const summary = results.reduce((acc, result) => {
if (result.status === 'fulfilled') {
acc.succeeded++;
acc.successResults.push(result.value);
} else {
acc.failed++;
acc.errors.push(result.reason);
}
return acc;
}, {
succeeded: 0,
failed: 0,
successResults: [],
errors: []
});
return summary;
} catch (error) {
// This will only catch errors in the Promise.allSettled() itself
console.error('Fatal error in batch operation:', error);
throw error;
}
}
Code language: JavaScript (javascript)
Browser Compatibility
Promise.allSettled() is supported in all modern browsers, but for older browsers, you might need a polyfill. Here’s a simple one:
if (!Promise.allSettled) {
Promise.allSettled = promises =>
Promise.all(
promises.map(p =>
p
.then(value => ({
status: 'fulfilled',
value
}))
.catch(reason => ({
status: 'rejected',
reason
}))
)
);
}
Code language: JavaScript (javascript)
Common Pitfalls to Avoid
- Don’t assume all promises will succeed just because Promise.allSettled() resolves:
// Bad practice
const results = await Promise.allSettled(promises);
results.forEach(result => console.log(result.value)); // May be undefined!
// Good practice
const results = await Promise.allSettled(promises);
results.forEach(result => {
if (result.status === 'fulfilled') {
console.log(result.value);
}
});
Code language: JavaScript (javascript)
- Don’t forget to handle memory considerations with large arrays:
// Better approach for large datasets
async function* batchProcess(promises, batchSize = 100) {
for (let i = 0; i < promises.length; i += batchSize) {
const batch = promises.slice(i, i + batchSize);
const results = await Promise.allSettled(batch);
yield results;
}
}
Code language: JavaScript (javascript)
When to Use Promise.allSettled()
- When you need to execute multiple independent operations and want to know the outcome of all of them
- When handling multiple API calls where some might fail but you want to process all results
- In scenarios where you’re performing batch operations and need to track both successes and failures
- When implementing retry mechanisms where you want to collect all errors before deciding how to proceed
Promise.allSettled() is particularly useful in scenarios where Promise.all() would be too strict (since it fails fast on any rejection) and Promise.race() would be insufficient (since it only provides the first settled result).
Conclusion
Promise.allSettled() is a powerful addition to JavaScript’s promise handling toolkit. It provides a robust way to handle multiple asynchronous operations where you need to track both successes and failures. By understanding its unique characteristics and proper usage patterns, you can write more resilient and maintainable asynchronous code.
Consider using Promise.allSettled() when you need to:
- Process all results regardless of success or failure
- Implement robust error handling for batch operations
- Track the status of multiple independent operations
For more information about JavaScript Promises, check out our guides on Promise.all() and Promise.race().