JavaScript Promises Tutorial - Section 3: Static Methods
Promise.allSettled() waits for all Promises to settle (either fulfill or reject), and returns an array describing the outcome of each Promise.
Promise.allSettled([promise1, promise2, promise3])
.then(results => {
// Always an array of result objects
results.forEach(result => {
if (result.status === 'fulfilled') {
console.log('Success:', result.value);
} else {
console.log('Failed:', result.reason);
}
});
});
Each result object has a status property:
// Fulfilled Promise
{ status: 'fulfilled', value: result }
// Rejected Promise
{ status: 'rejected', reason: error }
const promises = [
Promise.resolve('Success 1'),
Promise.reject(new Error('Failed')),
Promise.resolve('Success 2')
];
Promise.allSettled(promises)
.then(results => {
console.log(results);
// [
// { status: 'fulfilled', value: 'Success 1' },
// { status: 'rejected', reason: Error: Failed },
// { status: 'fulfilled', value: 'Success 2' }
// ]
});
| Feature | Promise.allSettled() | Promise.all() |
|---|---|---|
| Waits for | All to settle | All to fulfill |
| Rejects when | Never | Any rejects |
| Result | Array of result objects | Array of values |
| Use case | Partial success OK | All must succeed |
async function batchDeleteUsers(userIds) {
const deletePromises = userIds.map(id =>
deleteUser(id).catch(error => error)
);
const results = await Promise.allSettled(deletePromises);
const successful = results.filter(r => r.status === 'fulfilled');
const failed = results.filter(r => r.status === 'rejected');
console.log(`Deleted: ${successful.length}`);
console.log(`Failed: ${failed.length}`);
return {
successful: successful.map(r => r.value),
failed: failed.map(r => r.reason)
};
}
async function fetchAllData() {
const results = await Promise.allSettled([
fetchWeather(),
fetchNews(),
fetchStocks()
]);
return {
weather: results[0].status === 'fulfilled'
? results[0].value
: null,
news: results[1].status === 'fulfilled'
? results[1].value
: [],
stocks: results[2].status === 'fulfilled'
? results[2].value
: []
};
}
async function validateUser(userData) {
const validations = await Promise.allSettled([
validateEmail(userData.email),
validateUsername(userData.username),
validatePassword(userData.password),
checkUsernameAvailability(userData.username)
]);
const errors = validations
.filter(r => r.status === 'rejected')
.map(r => r.reason.message);
if (errors.length > 0) {
throw new Error(`Validation failed: ${errors.join(', ')}`);
}
return true;
}
const results = await Promise.allSettled(promises);
const successful = results
.filter(r => r.status === 'fulfilled')
.map(r => r.value);
const failed = results
.filter(r => r.status === 'rejected')
.map(r => r.reason);
console.log('Successful:', successful);
console.log('Failed:', failed);
async function processWithReport(items, processor) {
const promises = items.map(item => processor(item));
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
};
}
const report = await processWithReport(userIds, fetchUser);
console.log(`Processed ${report.successful}/${report.total} successfully`);
async function loadImageGallery(imageUrls) {
const loadPromises = imageUrls.map(url =>
new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve({ url, img, loaded: true });
img.onerror = () => reject({ url, loaded: false, error: 'Failed to load' });
img.src = url;
})
);
const results = await Promise.allSettled(loadPromises);
const loaded = results
.filter(r => r.status === 'fulfilled')
.map(r => r.value);
const failed = results
.filter(r => r.status === 'rejected')
.map(r => r.reason);
// Display loaded images
loaded.forEach(({ img }) => {
document.getElementById('gallery').appendChild(img);
});
// Show error for failed images
if (failed.length > 0) {
console.warn(`Failed to load ${failed.length} images`);
}
return {
loaded: loaded.length,
failed: failed.length,
total: imageUrls.length
};
}
if (!Promise.allSettled) {
Promise.allSettled = function(promises) {
return Promise.all(
promises.map(p =>
Promise.resolve(p)
.then(value => ({ status: 'fulfilled', value }))
.catch(reason => ({ status: 'rejected', reason }))
)
);
};
}
// Use Promise.all() when:
// - All operations MUST succeed
// - Fail-fast behavior is desired
const [user, posts, comments] = await Promise.all([
fetchUser(id),
fetchPosts(id),
fetchComments(id)
]);
// Use Promise.allSettled() when:
// - Partial success is acceptable
// - Need to know which succeeded/failed
const results = await Promise.allSettled([
sendEmail(user1),
sendEmail(user2),
sendEmail(user3)
]);
// Use Promise.race() when:
// - Only need the fastest result
// - Implementing timeouts
const data = await Promise.race([
fetchData(),
timeout(5000)
]);
Promise.allSettled() never rejectsstatus propertystatus before accessing value or reasonNext, we'll learn about Promise.any() for getting the first successful result!