Promise.any() takes an iterable of promises and returns a single promise that resolves as soon as any of the input promises fulfills. If all promises reject, it rejects with an AggregateError containing all rejection reasons.
π§ Understanding Promise.any
Atom 1: Purpose
Promise.any returns a promise that:
- β Resolves as soon as any input promise resolves
- β Rejects only if all input promises reject
Atom 2: Normalization
- Convert all inputs to promises with
Promise.resolve(...)
Atom 3: Resolve on First Fulfilled
- On first
.then, resolve the outer promise.
Atom 4: Track Rejections
- Maintain count of rejections.
- If all promises reject, reject with
AggregateError, which contains all rejection reasons.
Atom 5: Edge Case
- If input is empty β reject immediately with
AggregateError
β
Implementation: promiseAny
function promiseAny(iterable) { return new Promise((resolve, reject) => { const promises = Array.from(iterable); const errors = []; let rejectedCount = 0; if (promises.length === 0) { return reject(new AggregateError([], "All promises were rejected")); } promises.forEach((p, i) => { Promise.resolve(p) .then(resolve) .catch((err) => { errors[i] = err; rejectedCount++; if (rejectedCount === promises.length) { reject(new AggregateError(errors, "All promises were rejected")); } }); }); }); }
π§ͺ Example:
promiseAny([ Promise.reject("fail1"), new Promise(res => setTimeout(() => res("success"), 100)), Promise.reject("fail2") ]).then(console.log) .catch(console.error); // β "success"
β If all reject:
promiseAny([ Promise.reject("fail1"), Promise.reject("fail2") ]).then(console.log) .catch(err => { console.error(err instanceof AggregateError); // true console.error(err.errors); // ["fail1", "fail2"] });
Quick Quiz
Test your understanding with 3 quick questions
Q1When does Promise.any reject?
Q2What type of error does Promise.any throw when all promises reject?
Q3What happens when Promise.any is passed an empty array?