JavaScript’s Promise.any() is a powerful method introduced in ES2021 that helps manage multiple promises in a unique way. Unlike its cousins Promise.all() and Promise.race(), Promise.any() fulfills when any of the input promises fulfill, making it particularly useful for scenarios where you want to work with the first successful result.
In this comprehensive guide, we’ll explore Promise.any(), understand its use cases, and learn how to implement it effectively in your JavaScript applications.
Table of Contents
- How Promise.any() Works
- Key Features of Promise.any()
- Practical Use Cases
- Promise.any() vs Other Promise Methods
- Best Practices
- Browser Support and Polyfills
- Conclusion
How Promise.any() Works
Promise.any() takes an iterable of Promise objects and returns a single Promise. This returned promise fulfills when any of the input’s promises fulfills, with the value of the fulfilled promise. If all promises are rejected, it throws an AggregateError.
Basic Syntax
Promise.any(iterable)
Code language: JavaScript (javascript)
Simple Example
const promises = [
fetch('https://api.example.com/endpoint1'),
fetch('https://api.example.com/endpoint2'),
fetch('https://api.example.com/endpoint3')
];
Promise.any(promises)
.then(firstSuccess => console.log('First success:', firstSuccess))
.catch(error => console.log('All promises failed:', error));
Code language: JavaScript (javascript)
Key Features of Promise.any()
1. First Fulfillment Wins
The most distinctive feature of Promise.any() is that it resolves with the first promise that fulfills, ignoring any rejections unless all promises reject.
const promises = [
Promise.reject('Error 1'),
Promise.resolve('Success!'),
Promise.reject('Error 2')
];
Promise.any(promises)
.then(result => console.log(result)) // Outputs: 'Success!'
.catch(error => console.log(error));
Code language: JavaScript (javascript)
2. AggregateError Handling
When all promises reject, Promise.any() throws an AggregateError containing all rejection reasons.
const promises = [
Promise.reject('Error 1'),
Promise.reject('Error 2'),
Promise.reject('Error 3')
];
Promise.any(promises)
.then(result => console.log(result))
.catch(error => {
console.log(error.name); // AggregateError
console.log(error.errors); // ['Error 1', 'Error 2', 'Error 3']
});
Code language: JavaScript (javascript)
Practical Use Cases
1. Resource Loading with Fallbacks
const loadImage = src => {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = src;
});
};
const images = [
loadImage('/path/to/image1.jpg'),
loadImage('/path/to/image2.jpg'),
loadImage('/path/to/image3.jpg')
];
Promise.any(images)
.then(firstLoadedImage => document.body.appendChild(firstLoadedImage))
.catch(error => console.log('All images failed to load'));
Code language: JavaScript (javascript)
2. API Race with Timeout
const fetchWithTimeout = (url, timeout = 5000) => {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
return fetch(url, { signal: controller.signal })
.finally(() => clearTimeout(timeoutId));
};
const apis = [
fetchWithTimeout('https://api1.example.com/data'),
fetchWithTimeout('https://api2.example.com/data'),
fetchWithTimeout('https://api3.example.com/data')
];
Promise.any(apis)
.then(response => response.json())
.then(data => console.log('First successful response:', data))
.catch(error => console.log('All APIs failed'));
Code language: JavaScript (javascript)
Promise.any() vs Other Promise Methods
Comparison with Promise.race()
While Promise.race() settles with the first promise that settles (either fulfills or rejects), Promise.any() waits for the first fulfillment:
// Promise.race() example
Promise.race([
Promise.reject('Error'),
Promise.resolve('Success')
])
.then(console.log)
.catch(console.error); // Logs: Error
// Promise.any() example
Promise.any([
Promise.reject('Error'),
Promise.resolve('Success')
])
.then(console.log) // Logs: Success
.catch(console.error);
Code language: JavaScript (javascript)
Comparison with Promise.all()
Unlike Promise.all() which requires all promises to fulfill, Promise.any() needs only one fulfillment:
const promises = [
Promise.resolve(1),
Promise.reject('Error'),
Promise.resolve(3)
];
Promise.all(promises)
.then(console.log)
.catch(console.error); // Logs: Error
Promise.any(promises)
.then(console.log) // Logs: 1
.catch(console.error);
Code language: JavaScript (javascript)
Best Practices
1. Always Handle Errors
Promise.any(promises)
.then(result => {
// Handle success
})
.catch(error => {
if (error instanceof AggregateError) {
console.log('All promises rejected:', error.errors);
} else {
console.log('Unexpected error:', error);
}
});
Code language: JavaScript (javascript)
2. Consider Performance Implications
const optimizedPromises = promises.map(promise => {
return new Promise((resolve, reject) => {
promise
.then(resolve)
.catch(reject)
.finally(() => {
// Cleanup resources if needed
});
});
});
Code language: JavaScript (javascript)
Browser Support and Polyfills
Promise.any() is relatively new, so you might need a polyfill for older browsers. Here’s a simple polyfill implementation:
if (!Promise.any) {
Promise.any = function(promises) {
return new Promise((resolve, reject) => {
let errors = [];
let rejected = 0;
promises.forEach((promise, index) => {
Promise.resolve(promise)
.then(resolve)
.catch(error => {
errors[index] = error;
rejected++;
if (rejected === promises.length) {
reject(new AggregateError(errors, 'All promises rejected'));
}
});
});
});
};
}
Code language: JavaScript (javascript)
Conclusion
Promise.any() is a valuable addition to JavaScript’s promise toolkit, perfect for scenarios where you need the first successful result from multiple asynchronous operations. Its ability to handle multiple promises and provide meaningful error information through AggregateError makes it a powerful tool for modern web development.
For more information about handling promises in JavaScript, check out our guide on JavaScript Promise.race() and JavaScript Promise Methods, which cover other essential promise methods in detail.