Promise.all — A Pollyfill

Promise.all — A Pollyfill

What is a Promise anyway ?

According to MDN,

A Promise is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers with an asynchronous action’s eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point in the future.

A Promise is in one of these states:

  • pending: initial state, neither fulfilled nor rejected.
  • fulfilled: meaning that the operation was completed successfully.
  • rejected: meaning that the operation failed.

However I will not go into the detail of the Promises, as it would be a different article altogether. But I guess, this is enough for getting started.

The need for Pollyfill

Not all the browsers may natively support every functionality which comes in modern browsers. Pollyfills are meant to provide the users with same functionality to the people using older browsers.

About Promise.all

The Promise.all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises. This returned promise will resolve when all of the input's promises have resolved, or if the input iterable contains no promises. It rejects immediately upon any of the input promises rejecting or non-promises throwing an error, and will reject with this first rejection message / error.

function myAll(promises) {
  const _promises = promises.map((item) => item instanceof Promise ? item : Promise.resolve(item))

  if (_promises.length === 0) {
    return Promise.resolve([])
  }

  return new Promise((resolve, reject) => {
    const result = [];
    let fullfilledCount = 0;
    let isErrored = false;

    _promises.forEach((promise, index) => {
      promise.then((value) => {
        if (isErrored) return
        result[index] = value

        fullfilledCount += 1

        if (fullfilledCount == _promises.length) {
          return resolve(result)
        }

      }, (error) => {
        if (isErrored) return
        isErrored = true;
        reject(error)
      })
    })
  })


}

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

myAll([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});
// expected output: Array [3, 42, "foo"]

With the above code we should be able to achieve Promise.all behaviour in all the browsers. P.S : The above code is just a function. It would be better to add it in a prototype if you want to use it in a production ready codebase.

That’s all folks !!