DEV Community

Mitchell
Mitchell

Posted on

Promise static methods - JavaScript challenges

You can find all the code in this post at the repo Github.


Async programming Promise static methods related challenges


Promise.all()

/**
 * @param {Array} iterable
 * @return {Promise<Array>}
 */

// Async await
function promiseAll(iterable) {
  return new Promise((resolve, reject) => {
    let len = iterable.length;
    let resolved = 0;
    const results = Array.from({ length: len });

    if (len === 0) {
      resolve(results);
      return;
    }

    iterable.forEach(async (item, index) => {
      try {
        const result = await item;
        results[index] = result;
        resolved += 1;

        if (resolved === len) {
          resolve(results);
          return;
        }
      } catch (err) {
        reject(err);
      }
    });
  });
}

// Promise chaining
function promiseAll(iterable) {
  return new Promise((resolve, reject) => {
    const results = [];
    let resolved = 0;

    if (!iterable.length) {
      resolve(results);
      return;
    }

    iterable.forEach((item, index) => {
      Promise.resolve(item)
        .then((data) => {
          results[index] = data;
          resolved += 1;

          if (resolved === iterable.length) {
            resolve(results);
          }
        })
        .catch((err) => {
          reject(err);
        });
    });
  });
}

// Usage example
const p0 = Promise.resolve(3);
const p1 = 42;
const p2 = new Promise((resolve) => {
  setTimeout(() => {
    resolve("foo");
  }, 100);
});

promiseAll([p0, p1, p2]).then((data) => {
  console.log(data); // => [3, 42, 'foo']
});
Enter fullscreen mode Exit fullscreen mode

Promise.allSettled()

/**
 * @param {Array} iterable 
 * @return {Promise<Array<{status: 'fulfilled', value: *} | {status: 'rejected', reason: *}>>}
 */

function promiseAllSettled(iterable) {
  return new Promise((resolve) => {
    const len = iterable.length;
    const results = Array.from({ length: len });
    let pending = len;

    if (!pending) {
      resolve(results);
      return;
    }

    iterable.forEach(async (item, index) => {
      try {
        const value = await item;
        results[index] = {
          status: 'fulfilled',
          value,
        };
      } catch (err) {
        results[index] = {
          status: 'rejected',
          reason: err,
        };
      }

      pending -= 1;
      if (pending === 0) {
        resolve(results);
      }
    });
  });
}

// Usage example
const p0 = Promise.resolve(3);
const p1 = 42;
const p2 = new Promise((_, reject) => {
  setTimeout(() => {
    reject('foo');
  }, 100);
});

promiseAllSettled([p0, p1, p2])
  .then((data) => {
    console.log(data); 
  });
// [
//   { status: 'fulfilled', value: 3 },
//   { status: 'fulfilled', value: 42 },
//   { status: 'rejected', reason: 'foo' },
// ];
Enter fullscreen mode Exit fullscreen mode

Promise.any()

/**
 * @param {Array} iterable
 * @return {Promise}
 */

function promiseAny(iterable) {
  return new Promise((resolve, reject) => {
    const len = iterable.length;

    if (!len) {
      resolve(new AggregateError([]));
    }

    let pending = len;
    const errors = Array.from({ length: len });

    iterable.forEach(async (item, index) => {
      try {
        const value = await item;
        resolve(value);
      } catch (err) {
        errors[index] = err;
        pending -= 1;

        if (!pending) {
          reject(new AggregateError(errors));
        }
      }
    });
  });
}

// Usage example
const p0 = new Promise((resolve) => {
  setTimeout(() => {
    resolve(42);
  }, 100);
});
const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('Err!');
  }, 400);
});

promiseAny([p0, p1])
  .then((data) => {
    console.log(data); // => 42
  });
Enter fullscreen mode Exit fullscreen mode

Promise.race()

/**
 * @param {Array} iterable
 * @return {Promise}
 */

function promiseRace(iterable) {
  return new Promise((resolve, reject) => {
    if (!iterable.length) {
      return;
    }

    iterable.forEach(async (item) => {
      try {
        const result = await item;
        resolve(result);
      } catch (err) {
        reject(err);
      }
    });
  });
}

// Usage example
const p0 = new Promise((resolve) => {
  setTimeout(() => {
    resolve(42);
  }, 100);
});
const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("Err!");
  }, 400);
});

promiseRace([p0, p1]).then((data) => {
  console.log(data); // => 42
});
Enter fullscreen mode Exit fullscreen mode

Promise.reject()

/**
 * @param {*} reason
 * @returns Promise
 */

function promiseReject(reason) {
  return new Promise((_, reject) => {
    reject(reason);
  });
}

// Usage example
const promise = promiseReject('err');
promise.catch((err) => {
  console.log(`Error: ${err}`); // => Error: err
});
Enter fullscreen mode Exit fullscreen mode

Promise.resolve()

/**
 * @param {*} value
 * @return Promise
 */

function promiseResolve(value) {
  // Promise
  if (value instanceof Promise) {
    return value;
  }

  // Thenable
  if (typeof value.then === 'function') {
    return new Promise(value.then.bind(value));
  }

  return new Promise((resolve) => resolve(value));
}

// Usage example
const resolvedThenable = promiseResolve({
  then(resolve, reject) {
    resolve(1);
  }
})

const promise = resolvedThenable;
promise.then((data) => {
  console.log(data); // => 1
});
Enter fullscreen mode Exit fullscreen mode

Promise.withResolvers()

/**
 * @param {*} value
 * @return Promise
 */

function promiseResolve(value) {
  // Promise
  if (value instanceof Promise) {
    return value;
  }

  // Thenable
  if (typeof value.then === 'function') {
    return new Promise(value.then.bind(value));
  }

  return new Promise((resolve) => resolve(value));
}

// Usage example
const resolvedThenable = promiseResolve({
  then(resolve, reject) {
    resolve(1);
  }
})

const promise = resolvedThenable;
promise.then((data) => {
  console.log(data); // => 1
});
Enter fullscreen mode Exit fullscreen mode

Reference

Top comments (0)