Hone logo
Hone
Problems

Implementing Promise.race in JavaScript

The Promise.race() method is a powerful tool for resolving a promise based on the outcome of another promise that settles first. It's useful in scenarios like implementing timeouts, handling multiple asynchronous requests where you only need the first response, or coordinating asynchronous operations based on the earliest completion. This challenge asks you to implement Promise.race() from scratch, reinforcing your understanding of promises and asynchronous JavaScript.

Problem Description

You are tasked with implementing a Promise.race() function that takes an iterable (typically an array) of promises as input and returns a new promise. This new promise should resolve or reject based on the first promise in the input iterable to settle (either resolve or reject). The resolved or rejected value of the returned promise should be the same as the first promise that settles.

Key Requirements:

  • The function must accept an iterable (e.g., an array) of promises.
  • The returned promise should resolve or reject as soon as any of the input promises settle.
  • The resolved/rejected value of the returned promise must match the resolved/rejected value of the first settling promise.
  • If all input promises are pending and never settle, the returned promise should remain pending indefinitely.
  • The function should handle both resolved and rejected input promises correctly.

Expected Behavior:

The Promise.race() function should behave identically to the native Promise.race() method.

Edge Cases to Consider:

  • Empty input iterable: Should return a pending promise that never settles.
  • Input iterable containing non-promise values: These values should be treated as immediately resolved promises with a value of the non-promise value.
  • Promises that resolve/reject with the same value: The first to settle determines the outcome.
  • Promises that reject with different error messages: The first to reject determines the outcome.
  • Promises that resolve/reject asynchronously.

Examples

Example 1:

Input: [Promise.resolve(1), Promise.resolve(2)]
Output: 1
Explanation: The first promise resolves with 1, so the returned promise resolves with 1 immediately.

Example 2:

Input: [Promise.reject('error'), Promise.resolve(1)]
Output: 'error'
Explanation: The first promise rejects with 'error', so the returned promise rejects with 'error' immediately.

Example 3:

Input: [new Promise((resolve) => setTimeout(() => resolve('delayed resolve'), 100)), Promise.resolve('immediate resolve')]
Output: 'immediate resolve'
Explanation: The second promise resolves immediately, so the returned promise resolves with 'immediate resolve' before the first promise resolves.

Example 4: (Edge Case - Empty Input)

Input: []
Output: (A pending promise that never resolves or rejects)
Explanation:  An empty input iterable results in a pending promise.

Example 5: (Edge Case - Non-Promise Value)

Input: [123, Promise.resolve(456)]
Output: 123
Explanation: The number 123 is treated as an immediately resolved promise with the value 123.

Constraints

  • The input iterable can contain a maximum of 100 promises.
  • The input iterable will only contain promises or primitive values (numbers, strings, booleans, null, undefined, symbols).
  • The function should be implemented without relying on the native Promise.race() method.
  • Performance should be reasonable; avoid unnecessary computations or memory allocations. While not strictly enforced, aim for a solution that completes within a few milliseconds for typical inputs.

Notes

  • Remember that promises can be in one of three states: pending, fulfilled (resolved), or rejected.
  • Consider how to handle the different states of the input promises and how to propagate the outcome to the returned promise.
  • Think about how to efficiently determine which promise settled first.
  • You'll need to create a new promise and resolve or reject it based on the outcome of the first settling promise.
  • Pay close attention to the edge cases, especially the empty input iterable.
Loading editor...
javascript