Skip to content

Commit

Permalink
feat: implement Promise.any()
Browse files Browse the repository at this point in the history
  • Loading branch information
Shaban-Eissa committed Jun 4, 2024
1 parent 47f9d9c commit 3cc5cb7
Showing 1 changed file with 122 additions and 0 deletions.
122 changes: 122 additions & 0 deletions 34.implement-Promise.any.md
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.

0 comments on commit 3cc5cb7

Please sign in to comment.