Implement Promise.any from scratch
Implement promiseAny(promises) that mirrors Promise.any: it fulfills with the value of the first input that fulfills, and rejects only if every input rejects. Requirements: resolve as soon as any one settles successfully; if all reject, reject with an AggregateError whose errors array holds each rejection in input order; an empty input rejects immediately with an AggregateError.
function promiseAny(promises) {
// your code here
}
Write the implementation.
Return a new Promise. Track a pending counter and an errors array sized to the input. For each item, Promise.resolve(item).then(resolve, err => { errors[i] = err; if (--pending === 0) reject(new AggregateError(errors)); }). The first fulfillment wins; later settles are ignored.
- ✗Confusing the inversion: resolving on rejection instead of fulfillment
- ✗Rejecting on the first rejection rather than waiting for all to reject
- ✗Forgetting the empty-input case, which must reject with an
AggregateError
- →How does
Promise.anydiffer fromPromise.raceon a rejection? - →Why does an empty input reject rather than stay pending forever?
Solution
The first fulfillment wins; reject only when all reject.
function promiseAny(promises) {
return new Promise((resolve, reject) => {
const items = [...promises];
const errors = new Array(items.length);
let pending = items.length;
if (pending === 0) {
return reject(new AggregateError([], 'All promises were rejected')); // empty input
}
items.forEach((item, i) => {
Promise.resolve(item).then(resolve, (err) => { // first fulfillment → resolve
errors[i] = err; // collect errors by index
if (--pending === 0) { // all rejected
reject(new AggregateError(errors, 'All promises were rejected'));
}
});
});
});
}
How it works
Promise.resolve(item) wraps non-promises. The first success calls resolve and settles the outer promise — later callbacks are ignored. Each rejection writes its error by index and decrements pending; at zero every input has rejected and we reject an AggregateError listing them in input order. An empty input rejects at once.