Promise.any is a method in JavaScript used to handle multiple promises concurrently, but with a different behavior compared to Promise.all. It returns a single promise that resolves as soon as any of the promises in the iterable fulfills, or rejects if all the promises reject.
-
Concurrent Execution:
Promise.any
runs multiple promises in parallel.- It resolves as soon as one of the promises fulfills.
-
Resolved Value:
- When the first promise fulfills,
Promise.any
resolves with the value of that promise. - Example:
Promise.any([promise1, promise2]).then((value) => { console.log(value); });
- If
promise1
fulfills withvalue1
, the output will bevalue1
.
- When the first promise fulfills,
-
Rejection Handling:
- If all promises in the iterable reject,
Promise.any
rejects with anAggregateError
, which is a new error type that groups multiple individual errors. - Example:
Promise.any([promise1, promise2]).catch((error) => { console.log(error); });
- If both
promise1
andpromise2
reject,Promise.any
will reject with anAggregateError
containing all the rejection reasons.
- If all promises in the iterable reject,
https://bigfrontend.dev/problem/implement-Promise-any
Promise.any() takes an iterable of Promise objects and, as soon as one of the promises in the iterable fulfils, returns a single promise that resolves with the value from that promise
from MDN
Can you implement a any()
to work the same as Promise.any()
?
note
AggregateError
is not supported in Chrome yet, but you can still use it in your code since we will add the Class into your code. Do something like following:
new AggregateError('No Promise in Promise.any was resolved', errors);
/**
* @param {Array<Promise>} promises
* @return {Promise}
*/
function any(promises) {
if (promises.length === 0) {
return Promise.resolve();
}
let isFulfilled = false;
const errors = Array(promises.length);
let numOfErrors = 0;
return new Promise((resolve, reject) => {
promises.forEach((promise, i) => {
if (!(promise instanceof Promise)) {
promise = Promise.resolve(promise);
}
promise.then(
(value) => {
if (isFulfilled) {
return;
}
resolve(value);
isFulfilled = true;
},
(reason) => {
errors[i] = reason;
numOfErrors++;
if (numOfErrors === promises.length) {
reject(
new AggregateError(
'No Promise in Promise.any was resolved',
errors
)
);
}
}
);
});
});
}
const promise1 = new Promise((resolve, reject) => setTimeout(reject, 100, 'Error1'));
const promise2 = new Promise((resolve, reject) => setTimeout(resolve, 200, 'Success!'));
const promise3 = new Promise((resolve, reject) => setTimeout(reject, 300, 'Error3'));
Promise.any([promise1, promise2, promise3])
.then((value) => {
console.log(value); // 'Success!'
})
.catch((error) => {
console.error('All promises were rejected:', error);
});
- Race to Success: When you want to proceed as soon as any one of several asynchronous operations succeeds, such as loading the fastest resource among several mirrors.
- Fault Tolerance: When you want to use the first available data and ignore the rest, improving fault tolerance in case some promises fail.
- If the iterable passed to
Promise.any
is empty, it returns a promise that will be rejected with anAggregateError
. - If all promises reject, the rejection reason is an
AggregateError
containing an array of all rejection reasons.
By using Promise.any
, developers can efficiently handle scenarios where the first successful completion of any among several asynchronous tasks is sufficient, thereby enhancing performance and reliability in cases where multiple potential sources or paths are available.