-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
47f9d9c
commit 3cc5cb7
Showing
1 changed file
with
122 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
# 34. implement `Promise.any()` | ||
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. | ||
|
||
### Key Features of `Promise.any` | ||
|
||
1. **Concurrent Execution**: | ||
|
||
* `Promise.any` runs multiple promises in parallel. | ||
* It resolves as soon as one of the promises fulfills. | ||
2. **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 with `value1`, the output will be `value1`. | ||
3. **Rejection Handling**: | ||
|
||
* If all promises in the iterable reject, `Promise.any` rejects with an `AggregateError`, which is a new error type that groups multiple individual errors. | ||
* Example: `Promise.any([promise1, promise2]).catch((error) => { console.log(error); });` | ||
* If both `promise1` and `promise2` reject, `Promise.any` will reject with an `AggregateError` containing all the rejection reasons. | ||
|
||
|
||
### Problem | ||
|
||
https://bigfrontend.dev/problem/implement-Promise-any | ||
|
||
# | ||
|
||
### Problem Description | ||
|
||
> 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/any) | ||
|
||
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: | ||
|
||
```js | ||
new AggregateError('No Promise in Promise.any was resolved', errors); | ||
``` | ||
|
||
# | ||
|
||
### Solution | ||
|
||
```js | ||
/** | ||
* @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 | ||
) | ||
); | ||
} | ||
} | ||
); | ||
}); | ||
}); | ||
} | ||
``` | ||
|
||
### Example Usage | ||
|
||
```javascript | ||
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); | ||
}); | ||
``` | ||
|
||
### Use Cases | ||
|
||
* **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. | ||
|
||
### Important Notes | ||
|
||
* If the iterable passed to `Promise.any` is empty, it returns a promise that will be rejected with an `AggregateError`. | ||
* 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. |