The Promise.all() method
Basic Concept of Promise.all() Method
Promise.all() is a static method of the Promise object in ECMAScript 6. It takes an iterable collection of Promises (usually an array) and returns a new Promise instance. This new Promise is resolved only when all input Promises are successfully resolved. If any of the Promises is rejected, it will be immediately rejected.
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values); // [3, 42, "foo"]
});
How Promise.all() Works
The working mechanism of Promise.all() can be broken down into the following key points:
- It accepts an iterable object (usually an array) as an argument.
- Each element in the array is wrapped with Promise.resolve() to ensure they are all Promises.
- Returns a new Promise instance.
- When all input Promises are successfully resolved, the new Promise returns all results in an array.
- If any Promise is rejected, the new Promise is immediately rejected with that rejection reason.
const promises = [
fetch('/api/data1'),
fetch('/api/data2'),
fetch('/api/data3')
];
Promise.all(promises)
.then(responses => Promise.all(responses.map(r => r.json())))
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
Return Value Characteristics of Promise.all()
The Promise returned by Promise.all() has the following characteristics:
- The order of resolved values matches the input Promise order, even if some Promises resolve faster.
- If the input is an empty array, it immediately resolves with an empty array.
- Non-Promise values are treated as resolved Promises.
// Empty array case
Promise.all([]).then(values => {
console.log(values); // []
});
// Mixed Promises and non-Promise values
Promise.all([1, 2, Promise.resolve(3), Promise.resolve(4)])
.then(values => console.log(values)); // [1, 2, 3, 4]
Error Handling Mechanism
Error handling is one of the important features of Promise.all():
- It adopts a "fail-fast" mechanism, meaning the first rejected Promise causes the entire Promise.all() to be rejected.
- Results of other Promises are ignored, even if they are resolved later.
- Errors can be caught using .catch().
const p1 = new Promise((resolve) => setTimeout(resolve, 100, 'one'));
const p2 = new Promise((resolve, reject) => setTimeout(reject, 200, 'two'));
const p3 = new Promise((resolve) => setTimeout(resolve, 300, 'three'));
Promise.all([p1, p2, p3])
.then(values => console.log(values))
.catch(reason => console.log(reason)); // "two"
Practical Application Scenarios
Promise.all() has various practical scenarios in front-end development:
- Parallel multiple API requests.
- Loading multiple resources simultaneously.
- Batch processing data.
// Parallel requests to multiple API endpoints
const userId = 123;
const endpoints = [
`/api/users/${userId}`,
`/api/users/${userId}/posts`,
`/api/users/${userId}/followers`
];
const requests = endpoints.map(url => fetch(url).then(r => r.json()));
Promise.all(requests)
.then(([user, posts, followers]) => {
console.log('User:', user);
console.log('Posts:', posts);
console.log('Followers:', followers);
});
Difference from Promise.race()
Promise.all() is often compared with Promise.race(), with essential differences:
- Promise.all() waits for all Promises to complete.
- Promise.race() only waits for the first completed Promise (whether resolved or rejected).
const p1 = new Promise(resolve => setTimeout(resolve, 500, 'one'));
const p2 = new Promise(resolve => setTimeout(resolve, 100, 'two'));
Promise.all([p1, p2]).then(values => console.log(values)); // After 500ms: ["one", "two"]
Promise.race([p1, p2]).then(value => console.log(value)); // After 100ms: "two"
Advanced Usage Examples
Promise.all() can be combined with other Promise methods for more complex logic:
// Promise.all with timeout mechanism
function fetchWithTimeout(url, timeout = 5000) {
return Promise.race([
fetch(url),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Request timeout')), timeout)
)
]);
}
const urls = ['/api/data1', '/api/data2', '/api/data3'];
const requests = urls.map(url => fetchWithTimeout(url));
Promise.all(requests)
.then(responses => Promise.all(responses.map(r => r.json())))
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
Performance Optimization Considerations
Performance issues to note when using Promise.all():
- Avoid initiating too many parallel requests at once.
- Consider processing large numbers of Promises in batches.
- Be mindful of memory usage.
// Processing large numbers of Promises in batches
async function processInBatches(items, batchSize, processItem) {
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
await Promise.all(batch.map(processItem));
console.log(`Processed batch ${i / batchSize + 1}`);
}
}
const items = Array(1000).fill().map((_, i) => i);
processInBatches(items, 50, item => {
return new Promise(resolve => {
// Simulate asynchronous processing
setTimeout(() => resolve(item * 2), Math.random() * 100);
});
});
Browser Compatibility
Browser support for Promise.all():
- Fully supported in modern browsers.
- Not supported in IE11 and below.
- Supported in Node.js 0.12 and above.
For unsupported environments, a polyfill can be used:
// Simple Promise.all polyfill
if (!Promise.all) {
Promise.all = function(promises) {
return new Promise(function(resolve, reject) {
if (!Array.isArray(promises)) {
return reject(new TypeError('Argument must be an array'));
}
var remaining = promises.length;
if (remaining === 0) {
return resolve([]);
}
function resolver(index) {
return function(value) {
resolveAll(index, value);
};
}
function resolveAll(index, value) {
results[index] = value;
if (--remaining === 0) {
resolve(results);
}
}
var results = new Array(remaining);
for (var i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then(resolver(i), reject);
}
});
};
}
Comparison with Promise.allSettled()
ES2020 introduced Promise.allSettled(), which differs from Promise.all():
- Promise.allSettled() waits for all Promises to complete (whether resolved or rejected).
- Returns an array of results containing the status and value/reason of each Promise.
const promises = [
Promise.resolve(1),
Promise.reject('Error occurred'),
Promise.resolve(3)
];
Promise.allSettled(promises).then(results => {
results.forEach(result => console.log(result));
/*
Output:
{status: "fulfilled", value: 1}
{status: "rejected", reason: "Error occurred"}
{status: "fulfilled", value: 3}
*/
});
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn