JavaScript Interview Question: How to Implement a Promise?
Tags: Promises, JavaScript, Software Development, Programming, Web Development

JavaScript Interview Question: How to Implement a Promise?

Write a Promise function step by step.

Photo by marcos mayer on Unsplash

The Promise is a core feature of JavaScript from ES2015. A promise is an object that may produce a single value some time in the future: either a resolved value or a reason that it’s not resolved (e.g., a network error occurred). A promise may be in one of 3 possible states: fulfilled(resolved), rejected, or pending. Promise users can attach callbacks to handle the fulfilled value or the reason for rejection.

Our Promise function should adhere to the Promise A+ specification, and if you are not familiar with it, please read this specification first.

Next, let’s write a Promise function together.

Executor

We know that when you create a Promise instance, we need to pass in an executor function. The executor function should take two function arguments: the resolve function and the rejec t function. When the resolve function is invoked, the promise instance becomes resolved. If the executor function performs an exception, the reject function should be called, and the state of the Promise instance will be rejected.

Now, let’s write a MyPromise function that basically meets these requirements.

Attention, for better understanding, I use ES6’s class syntax. This is actually the syntax sugar for the constructor function.

All right, now let’s simply test the function we just wrote.

let p1 = new MyPromise((resolve, reject) => {

resolve(1);

}) let p2 = new MyPromise((resolve, reject) => {

reject(2);

}) console.log(p1);

console.log(p2);

Ok, now we’ve written the MyPromise function and can correctly change the state through the resolve and reject functions.

Then

Next, let’s write the .then method for the MyPromise. The then method should have two function arguments, the first will be executed after the Promise succeeds and the second will be executed after the Promise fails.

At the same time, the .then method supports chain calls, which return an promise instance after each execution.

new Promise((resolve, reject) => {

resolve(1)

}).then(null, error => {

console.log(error)

}).then(value => {

console.log(1)

});

Now let’s refine the previous code.

catch

The .catch method is used to catch exceptions. It is the same as the second callback function for the .then method.

So, we can just write it this way:

catch(rejectFn) {

return this.then(null, rejectFn)

}

resolve and reject

We know the Promise.resolve(…) method is to return an instance of a Promise with a resolved state and the Promise.reject(…) method is to return an instance of a Promise with a rejected state. These two methods are very easy to implement:

static resolve(result) {

return new MyPromise(resolve => {

resolve(result)

})

} static reject(reason) {

return new MyPromise((_, reject) => {

reject(reason);

})

}

finally

The finally() method returns a Promise. When the promise is settled, i.e either fulfilled or rejected, the specified callback function is executed. This provides a way for code to be run whether the promise was fulfilled successfully or rejected once the Promise has been dealt with.

This is code snippet:

finally(finallyFn) {

let P = this.constructor;

return this.then(

value => P.resolve(finallyFn()).then(() => value),

reason => P.reject(finallyFn()).then(() => reason)

)

}

This is full code:

all

The Promise.all() method returns a single Promise that fulfills when all of the promises passed as an iterable have been fulfilled or when the iterable contains no promises or when the iterable contains promises that have been fulfilled and non-promises that have been returned. It rejects with the reason of the first promise that rejects, or with the error caught by the first argument if that argument has caught an error inside it using try/catch/throw blocks.

// Receive array parameter

static all(promiseList) {

// Returns a new instance

return new MyPromise((resolve, reject) => {

let index = 0,

results = [];



for(let i = 0; i < promiseList.length; i++) {

let item = promiseList[i];



if(!(item instanceof MyPromise)) return;



item.then(result => {

index++;

results[i] = result;

if(index === promiseList.length) {

resolve(results);

}

}).catch(reason => {

reject(reason);

})

}

})

}

A note from JavaScript In Plain English

We have launched three new publications! Show some love for our new publications by following them: AI in Plain English, UX in Plain English, Python in Plain English — thank you and keep learning!

We are also always interested in helping to promote quality content. If you have an article that you would like to submit to any of our publications, send us an email at submissions@plainenglish.io with your Medium username and we will get you added as a writer. Also let us know which publication/s you want to be added to.