The JavaScript Promise.allSettled()
method, introduced in ES2020, is a powerful tool for handling multiple promises simultaneously. Unlike Promise.all()
, which short-circuits when any promise rejects, Promise.allSettled()
waits for all promises to settle, meaning they either resolve or reject. This comprehensive guide will explore everything you need to know about Promise.allSettled()
, including what it is, why it is useful, where and how to use it, and when it is most beneficial.
What is the JavaScript Promise.allSettled() Method?
Promise.allSettled()
is a method that takes an iterable of promises and returns a promise that resolves after all of the given promises have either resolved or rejected. The returned promise resolves to an array of objects, each describing the outcome of each promise.
Syntax
The syntax for using Promise.allSettled()
is:
Promise.allSettled(iterable)
.then((results) => {
// Handle results
});
Example
const promise1 = Promise.resolve('First Promise');
const promise2 = Promise.reject('Second Promise Rejected');
const promise3 = Promise.resolve('Third Promise');
Promise.allSettled([promise1, promise2, promise3])
.then((results) => {
console.log(results);
});
// Output:
// [
// { status: 'fulfilled', value: 'First Promise' },
// { status: 'rejected', reason: 'Second Promise Rejected' },
// { status: 'fulfilled', value: 'Third Promise' }
// ]
In this example, Promise.allSettled()
returns an array of objects indicating whether each promise was fulfilled or rejected.
Why Use the JavaScript Promise.allSettled() Method?
Promise.allSettled()
offers several benefits:
- Reliability: It ensures that you get the results of all promises, even if some of them fail.
- Error Handling: Allows you to handle errors individually without short-circuiting other promises.
- Comprehensive Results: Provides a complete picture of all promise outcomes.
Reliability Example
Without Promise.allSettled()
:
const promise1 = Promise.resolve('First Promise');
const promise2 = Promise.reject('Second Promise Rejected');
const promise3 = Promise.resolve('Third Promise');
Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results);
})
.catch((error) => {
console.error('One of the promises rejected:', error);
});
// Output: One of the promises rejected: Second Promise Rejected
With Promise.allSettled()
:
Promise.allSettled([promise1, promise2, promise3])
.then((results) => {
console.log(results);
});
// Output:
// [
// { status: 'fulfilled', value: 'First Promise' },
// { status: 'rejected', reason: 'Second Promise Rejected' },
// { status: 'fulfilled', value: 'Third Promise' }
// ]
Where to Use the JavaScript Promise.allSettled() Method?
Promise.allSettled()
can be used in various scenarios where you need to handle multiple promises simultaneously and want to ensure all results are captured:
- Batch Processing: Process multiple asynchronous tasks and handle all outcomes.
- API Requests: Make multiple API requests and process all responses.
- Data Aggregation: Aggregate data from multiple sources, handling all results.
Batch Processing Example
const tasks = [
new Promise((resolve) => setTimeout(() => resolve('Task 1 Complete'), 1000)),
new Promise((resolve, reject) => setTimeout(() => reject('Task 2 Failed'), 2000)),
new Promise((resolve) => setTimeout(() => resolve('Task 3 Complete'), 3000))
];
Promise.allSettled(tasks)
.then((results) => {
results.forEach((result) => console.log(result));
});
// Output after 3 seconds:
// { status: 'fulfilled', value: 'Task 1 Complete' }
// { status: 'rejected', reason: 'Task 2 Failed' }
// { status: 'fulfilled', value: 'Task 3 Complete' }
API Requests Example
const apiRequests = [
fetch('https://api.example.com/data1'),
fetch('https://api.example.com/data2'),
fetch('https://api.example.com/data3')
];
Promise.allSettled(apiRequests)
.then((responses) => {
responses.forEach((response, index) => {
if (response.status === 'fulfilled') {
console.log(`API ${index + 1} response:`, response.value);
} else {
console.error(`API ${index + 1} error:`, response.reason);
}
});
});
Data Aggregation Example
const dataSources = [
Promise.resolve({ source: 'Source 1', data: [1, 2, 3] }),
Promise.reject('Source 2 Failed'),
Promise.resolve({ source: 'Source 3', data: [4, 5, 6] })
];
Promise.allSettled(dataSources)
.then((results) => {
const aggregatedData = results.reduce((acc, result) => {
if (result.status === 'fulfilled') {
acc.push(...result.value.data);
}
return acc;
}, []);
console.log('Aggregated Data:', aggregatedData);
});
// Output: Aggregated Data: [1, 2, 3, 4, 5, 6]
How to Use the JavaScript Promise.allSettled() Method?
Basic Usage
To use Promise.allSettled()
, pass an iterable of promises and handle the results.
const promises = [
Promise.resolve('Success'),
Promise.reject('Error'),
Promise.resolve('Another Success')
];
Promise.allSettled(promises)
.then((results) => {
results.forEach((result) => {
if (result.status === 'fulfilled') {
console.log('Fulfilled:', result.value);
} else {
console.log('Rejected:', result.reason);
}
});
});
Using with async/await
You can use Promise.allSettled()
with async/await
for a cleaner syntax.
const promises = [
Promise.resolve('Success'),
Promise.reject('Error'),
Promise.resolve('Another Success')
];
(async () => {
const results = await Promise.allSettled(promises);
results.forEach((result) => {
if (result.status === 'fulfilled') {
console.log('Fulfilled:', result.value);
} else {
console.log('Rejected:', result.reason);
}
});
})();
Handling Errors Individually
With Promise.allSettled()
, you can handle errors individually without affecting the other promises.
const promises = [
Promise.resolve('Success'),
Promise.reject('Error'),
Promise.resolve('Another Success')
];
Promise.allSettled(promises)
.then((results) => {
results.forEach((result) => {
if (result.status === 'fulfilled') {
console.log('Fulfilled:', result.value);
} else {
console.error('Rejected:', result.reason);
}
});
});
When to Use the JavaScript Promise.allSettled() Method?
When Handling Multiple Promises
Use Promise.allSettled()
when you need to handle multiple promises and ensure all outcomes are captured.
const tasks = [
new Promise((resolve) => setTimeout(() => resolve('Task 1 Complete'), 1000)),
new Promise((resolve, reject) => setTimeout(() => reject('Task 2 Failed'), 2000)),
new Promise((resolve) => setTimeout(() => resolve('Task 3 Complete'), 3000))
];
Promise.allSettled(tasks)
.then((results) => {
results.forEach((result) => {
if (result.status === 'fulfilled') {
console.log('Fulfilled:', result.value);
} else {
console.error('Rejected:', result.reason);
}
});
});
When Aggregating Data from Multiple Sources
Use Promise.allSettled()
to aggregate data from multiple sources, ensuring all results are handled.
const dataSources = [
Promise.resolve({ source: 'Source 1', data: [1, 2, 3] }),
Promise.reject('Source 2 Failed'),
Promise.resolve({ source: 'Source 3', data: [4, 5, 6] })
];
Promise.allSettled(dataSources)
.then((results) => {
const aggregatedData = results.reduce((acc, result) => {
if (result.status === 'fulfilled') {
acc.push(...result.value.data);
}
return acc;
}, []);
console.log('Aggregated Data:', aggregatedData);
});
When Making Multiple API Requests
Use Promise.allSettled()
to handle multiple API requests and ensure all responses are processed.
const apiRequests = [
fetch('https://api.example.com/data1'),
fetch('https://api.example.com/data2'),
fetch('https://
api.example.com/data3')
];
Promise.allSettled(apiRequests)
.then((responses) => {
responses.forEach((response, index) => {
if (response.status === 'fulfilled') {
console.log(`API ${index + 1} response:`, response.value);
} else {
console.error(`API ${index + 1} error:`, response.reason);
}
});
});
Combining Promise.allSettled() with Promise.all()
Use Promise.allSettled()
to handle a batch of promises and then use Promise.all()
to process the results further.
const tasks = [
new Promise((resolve) => setTimeout(() => resolve('Task 1 Complete'), 1000)),
new Promise((resolve, reject) => setTimeout(() => reject('Task 2 Failed'), 2000)),
new Promise((resolve) => setTimeout(() => resolve('Task 3 Complete'), 3000))
];
Promise.allSettled(tasks)
.then((results) => {
const fulfilledTasks = results.filter(result => result.status === 'fulfilled');
return Promise.all(fulfilledTasks.map(result => result.value));
})
.then((fulfilledResults) => {
console.log('All fulfilled results:', fulfilledResults);
});
Using Promise.allSettled() in React for Data Fetching
Use Promise.allSettled()
in a React component to fetch data from multiple endpoints and handle all responses.
import React, { useEffect, useState } from 'react';
const DataFetchingComponent = () => {
const [data, setData] = useState([]);
const [errors, setErrors] = useState([]);
useEffect(() => {
const fetchData = async () => {
const endpoints = [
'https://api.example.com/data1',
'https://api.example.com/data2',
'https://api.example.com/data3'
];
const promises = endpoints.map((endpoint) => fetch(endpoint).then((res) => res.json()));
const results = await Promise.allSettled(promises);
const successfulData = [];
const failedData = [];
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
successfulData.push(result.value);
} else {
failedData.push(`Error fetching data from ${endpoints[index]}: ${result.reason}`);
}
});
setData(successfulData);
setErrors(failedData);
};
fetchData();
}, []);
return (
<div>
<h1>Fetched Data</h1>
{data.map((item, index) => (
<div key={index}>
<pre>{JSON.stringify(item, null, 2)}</pre>
</div>
))}
<h1>Errors</h1>
{errors.map((error, index) => (
<div key={index}>
<p>{error}</p>
</div>
))}
</div>
);
};
export default DataFetchingComponent;
Summary
The JavaScript Promise.allSettled()
method is a powerful tool for handling multiple promises and ensuring all results are captured, regardless of whether they resolve or reject. It provides a reliable way to manage asynchronous operations, handle errors individually, and aggregate data from multiple sources. By understanding and using Promise.allSettled()
effectively, you can improve the robustness and readability of your code. Practice using Promise.allSettled()
in various scenarios to see its full potential and enhance your JavaScript programming skills.
Leave a Reply