Promise.race polyfill

Promises are one of the trickiest things to understand in JavaScript thus it is common in interviews to ask for writing the code (polyfill) for methods like Promise.race().

According to MDN –

The Promise.race() method returns a promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise.

Polyfill for Promise.race()

Reading the definition, we can derive the problem statement into sub-problems to implement the Promise.race method.

  1. It returns a promise.
  2. The returned promise fulfills or rejects as soon as any one of the input promises fulfills or rejects.
  3. Returned promise resolves with the value of the input promise or rejects with the reason of the input promise.

Thus we can create a function that will take an array of promises as input and return a new promise from that function, inside this promise iterate the input promises and resolve or reject as soon as any of them resolves or rejects.

const race = function(promisesArray) {
  return new Promise((resolve, reject) => {
    promisesArray.forEach((promise) => {
      Promise.resolve(promise)
        .then(resolve, reject) // resolve, when any of the input promise resolves
        .catch(reject); // reject, when any of the input promise rejects
    });
  });
};

Test case 1.

Input:
const test1 = new Promise(function (resolve, reject) {
  setTimeout(resolve, 500, 'one');
});

const test2 = new Promise(function (resolve, reject) {
  setTimeout(resolve, 100, 'two');
});

const test3 = new Promise(function (resolve, reject) {
  setTimeout(reject, 200, 'three');
});

race([test1, test2, test3]).then(function (value) {
  // first two resolve, 3rd fails, but promise2 is faster
  console.log(value);
}).catch(function (err){
  console.log(err);
});

Output:
"two"

Test case 2.

Input:
const test1 = new Promise(function (resolve, reject) {
  setTimeout(resolve, 500, 'one');
});

const test2 = new Promise(function (resolve, reject) {
  setTimeout(resolve, 100, 'two');
});

const test3 = new Promise(function (resolve, reject) {
  setTimeout(reject, 40, 'three');
});

race([test1, test2, test3]).then(function (value) {
  // first two resolve, 3rd fails, but promise3 is faster
  console.log(value);
}).catch(function (err){
  console.log(err);
});

Output:
"three"