Q21: Implement a polyfill for Promise.race().

Difficulty:IntermediateTopic:Promises

Answer

Promise.race() returns a promise that settles as soon as one of the input promises settles. The first settlement may be either fulfillment or rejection.

if (!Promise.myRace) {
  Promise.myRace = function (iterable) {
    return new Promise((resolve, reject) => {
      let iterator;

      try {
        iterator = iterable[Symbol.iterator]();
      } catch (error) {
        reject(error);
        return;
      }

      try {
        while (true) {
          const step = iterator.next();

          if (step.done) {
            break;
          }

          Promise.resolve(step.value).then(resolve, reject);
        }
      } catch (error) {
        reject(error);
      }
    });
  };
}

Promise.myRace([
  new Promise(resolve => setTimeout(() => resolve("slow"), 200)),
  new Promise(resolve => setTimeout(() => resolve("fast"), 50))
]).then(console.log);
// fast

Explanation

Each input is passed through Promise.resolve(). The first fulfillment or rejection that settles the outer promise determines its outcome. Later settlements have no effect on the already-settled promise.

An empty iterable leaves the returned promise pending forever. Exact native compatibility requires careful handling of iterator closing, constructor semantics, and abrupt completion.

Key Takeaways
  • Promise.race settles according to the first input to settle.
  • The winning input may fulfill or reject, and an empty iterable leaves the promise pending.