Skip to content

Latest commit

 

History

History
122 lines (90 loc) · 4.14 KB

34.implement-Promise.any.md

File metadata and controls

122 lines (90 loc) · 4.14 KB

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

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);

Solution

/**
 * @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

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.