JavaScript Promises Tutorial - Section 3: Static Methods
Promise.any() returns a Promise that fulfills as soon as any of the input Promises fulfills. It only rejects if all Promises reject.
Promise.any([promise1, promise2, promise3])
.then(result => {
// First successful result
})
.catch(error => {
// AggregateError if ALL failed
});
const promises = [
Promise.reject('Error 1'),
Promise.resolve('Success!'),
Promise.reject('Error 2')
];
Promise.any(promises)
.then(result => {
console.log(result); // "Success!"
})
.catch(error => {
console.error('All failed');
});
| Feature | Promise.any() | Promise.race() |
|---|---|---|
| Resolves when | First fulfillment | First settlement (fulfill or reject) |
| Rejects when | All reject | First rejection |
| Ignores | Rejections (until all fail) | Nothing |
| Use case | Fallback sources | Fastest response |
async function fetchFromMultipleSources(endpoint) {
const sources = [
fetch(`https://api1.example.com${endpoint}`),
fetch(`https://api2.example.com${endpoint}`),
fetch(`https://api3.example.com${endpoint}`)
];
try {
const response = await Promise.any(sources);
return await response.json();
} catch (error) {
throw new Error('All API sources failed');
}
}
fetchFromMultipleSources('/data')
.then(data => console.log('Got data:', data))
.catch(error => console.error(error));
function loadScript(src) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.onload = () => resolve(src);
script.onerror = () => reject(new Error(`Failed: ${src}`));
script.src = src;
document.head.appendChild(script);
});
}
const cdns = [
'https://cdn1.example.com/library.js',
'https://cdn2.example.com/library.js',
'https://cdn3.example.com/library.js'
];
Promise.any(cdns.map(loadScript))
.then(src => console.log('Loaded from:', src))
.catch(() => console.error('All CDNs failed'));
async function queryFromReplicas(query) {
const replicas = [
queryDatabase('primary', query),
queryDatabase('replica1', query),
queryDatabase('replica2', query)
];
return Promise.any(replicas);
}
queryFromReplicas('SELECT * FROM users')
.then(results => console.log('Query results:', results))
.catch(error => console.error('All replicas failed'));
When all Promises reject, Promise.any() throws an AggregateError containing all rejection reasons:
const promises = [
Promise.reject(new Error('Error 1')),
Promise.reject(new Error('Error 2')),
Promise.reject(new Error('Error 3'))
];
Promise.any(promises)
.catch(error => {
console.log(error instanceof AggregateError); // true
console.log(error.errors); // Array of all errors
error.errors.forEach((err, index) => {
console.log(`Promise ${index + 1}:`, err.message);
});
});
async function fetchWithFallbacks(urls) {
try {
const response = await Promise.any(
urls.map(url => fetch(url))
);
return await response.json();
} catch (error) {
if (error instanceof AggregateError) {
console.error('All sources failed:');
error.errors.forEach((err, i) => {
console.error(` Source ${i + 1}:`, err.message);
});
}
throw new Error('Failed to fetch from any source');
}
}
function loadImage(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = () => reject(new Error(`Failed: ${url}`));
img.src = url;
});
}
async function loadImageWithFallbacks(imageName) {
const sources = [
`https://cdn1.example.com/images/${imageName}`,
`https://cdn2.example.com/images/${imageName}`,
`https://cdn3.example.com/images/${imageName}`,
`/local/images/${imageName}` // Local fallback
];
try {
const img = await Promise.any(sources.map(loadImage));
document.body.appendChild(img);
return img;
} catch (error) {
console.error('All image sources failed');
// Show placeholder
const placeholder = document.createElement('div');
placeholder.textContent = 'Image not available';
document.body.appendChild(placeholder);
}
}
loadImageWithFallbacks('photo.jpg');
function timeout(ms) {
return new Promise((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), ms)
);
}
async function fetchWithFallbacksAndTimeout(urls, timeoutMs) {
const fetchPromises = urls.map(url =>
Promise.race([
fetch(url),
timeout(timeoutMs)
])
);
return Promise.any(fetchPromises);
}
fetchWithFallbacksAndTimeout([
'https://slow-api.com/data',
'https://fast-api.com/data'
], 5000)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('All attempts failed or timed out'));
if (!Promise.any) {
Promise.any = function(promises) {
return new Promise((resolve, reject) => {
const errors = [];
let rejectedCount = 0;
promises.forEach((promise, index) => {
Promise.resolve(promise)
.then(resolve)
.catch(error => {
errors[index] = error;
rejectedCount++;
if (rejectedCount === promises.length) {
reject(new AggregateError(
errors,
'All promises were rejected'
));
}
});
});
});
};
}
// Promise.all() - All must succeed
const [a, b, c] = await Promise.all([p1, p2, p3]);
// Rejects if ANY fails
// Promise.allSettled() - Wait for all, get all results
const results = await Promise.allSettled([p1, p2, p3]);
// Never rejects, returns status for each
// Promise.race() - First to settle wins
const result = await Promise.race([p1, p2, p3]);
// Settles with first (success or failure)
// Promise.any() - First success wins
const result = await Promise.any([p1, p2, p3]);
// Rejects only if ALL fail
Promise.any() resolves with first successAggregateError when all rejectPromise.race() - ignores rejectionsNow that you've mastered all Promise static methods, let's move on to async/await!