The Promise in JavaScript

Rajeev R
The Startup
Published in
6 min readSep 11, 2019
The Promise should not get rejected
Promise should not be rejected.

A Promise is an object representing the eventual completion or failure of an asynchronous operation.

This is what MDN define Promise for JS. A Promise can have one of three state. It can be Resolved, Rejected or Pending.

Lets look at the Promise Object and its prototype methods to better understand how it works.

A Promise Object has five static methods and three prototype methods as shown in the object diagram below.

It also has two internal properties [[PromiseStatus]] and [[PromiseValue]] which is not accessible directly but play a very important role by holding the status and the result(value) of a promise instance.

Promise constructor and prototype relationship diagram

Before we go in-depth of promise object and its methods. Let me tell you a story which you can use later to understand how promise works. For now I can tell you that Promise work the same way you do any promise to someone.

A sort Promise Story:

One Friday while leaving my office , I called my wife and asked her to make my favourite dish . She replied , yes I promise (promise1) I will serve your favourite dish for dinner today when you are back home. She also mentioned, “ I need to go to supermarket to get the ingredients before I start”.

[Promise1 “make dish” is made] [promise status is — pending]

While driving back home I thought of calling my friend for dinner. I called my friend and asked him to come home with few canes of beer. He promised, and said he will be there for dinner.

[Promise2 “come home” is made] [promise status is pending]

Well, when I reached home My friend had already come [Promise2 resolved] but my wife could not make my favourite dish as she could not find all the ingredient(instead she had cooked something else)[Promise1 rejected]

The story continues..

In the above sort story we have two promises makeDish and comeHome . Lets creat this promises using JavaScript Object and understand its working.

The constructor syntax of a promise :

let promise = new Promise((resolve, reject) => {
// executor (executor code goes here)
});

Executor function:

(resolve, reject)=>{ //body of the executor function}

The executor function takes another two parameter resolve and reject . resolve and reject are the instance methods of Promise object so you don’t have to write this methods.(see prototype diagram above)

The body of the executor function is where you can do an asynchronous call such as an XHR call or fetch API call . And based on the XHR/fetch calll status you can resolve or reject the promise. We will have a look on asynchronous call soon.

let makeDish = new Promise((resolve, reject)=>{let allIngredientFound = false;// this can be a result of an asynchronous call.if(allIngredientFound){    resolve(console.log(“favoruit dish cooked”));}else{    reject(console.log(“Dish not cooked as all ingredient not     found”));}});//result - Dish not cooked as all ingredient not found

*you will get "uncaught in promise" error as reject is not handled via catch();

We will soon see how to catch rejected promise.

let comeHome = new Promise((resolve, reject)=>{let buyDrink = true;if(buyDrink){    resolve(console.log("came home with drink"))}else{    reject(console.log("could not come home as drink not found"))}});// result - came home with drink

We created a “makeDish” promise by instantiating Promise constructor using new operator (yes, Promise is a constructor pattern). The Promise constructor takes a call-back function (often called executor function) as parameter.

In our “makeDish” Example we do not have any asynchronous call but we have a variable “allIngredientFound” which holds a value “false” . Lets consider this “allIngredientFound” is a result of an asynchronous call which return “false”.

Next, based on the value of “allIngredientFound” we resolve or reject the promise by providing the “result data” or “rejection reason”.

if(allIngredientFound){    resolve("favourit dish cooked");}else{    reject("Dish not cooked as all ingredient not found");}

The “result data” or “reason for rejection” can be any data you want such as “ favorite dish cooked” or it can be a raw/processed data received from an asynchronous call.

.then()

Well, in the above example two promises ( makeDish and comeHome) are created but how can one access this promise. I mean if someone make a promise to you how would you know the result(status of the promise).

To know the status of the promise one need to subscribe to the promise using Promise prototype method ‘then()’.

Then() takes two callbacks as parameter. The first callback parameter is executed when promise is resolved and the second callback (optional) is executed if the promise is rejected.

let comeHome = new Promise((resolve, reject)=>{let buyDrink = false;if(buyDrink){    resolve("came home with drink")}else{    reject("could not come home as drink not found")}});comeHome.then(result => console.log(result), error => console.log(error));//Result : could not come home as drink is not found

Here the promise is rejected as buyDrink = false; and the rejected promise is catched using then();

Note: first callback in then() is not called as the promise is rejected. Try making “buyDrink = true” in above code and you will see that the result is “came home with drink” and the first callback inside then() will be called.

.catch()

As mentioned, second callback is optional. Usually to get the status of rejected promise we use other prototype method catch()

Catch method takes a callback as argument

comeHome.catch(error=>console.log(error));//This interns internally calls comeHome.then(undefine, error=>console.log(error));

.finally()

The finally method will be executed even when promise is rejected or resolved. It is useful if one need to do some processing after promise is resolved or rejected.

comeHome.then(result=>console.log(result)).catch(error=>console.log(error).finally(()=>console.log(“finally do something”)));

Static Methods

Promise has five static methods as mentioned at the beginning. We have already seen how and where to use promise.resolve() and promise.reject(). Lets look other three methods one by one.

.all()

Assume that you need to do multiple async call at once using promise to get different JSON data from server and aggregate the result.

To perform this you can use promise.all() by passing an array of promise as a parameter which will return you a single promise.

Promise.all([new Promise(resolve => setTimeout(() => {resolve(3)}, 1000)),new Promise(resolve => setTimeout(() => {resolve(1)}, 3000)),new Promise(resolve => setTimeout(() => {resolve(2)}, 2000)),]).then(res=>console.log(res));Result — [3,2,1]*Note that the result is an array object.

Lets see a real server call example.

let urls = [
"https://swapi.co/api/people/1/",
"https://swapi.co/api/planets/3/", "https://swapi.co/api/starships/9/"
];
let requests = urls.map(url => fetch(url));Promise.all(requests).then(responses => responses.forEach( response => console.info(response)));

The response will be an array object having JSON data from the URLs.

If any of the promise fails the promise returned by Promise.all(), immediately rejects and returns the Error provided in reject().

Promise.all([new Promise(resolve => setTimeout(() => {resolve(3)}, 1000)),new Promise(resolve => setTimeout(() => {reject(new Error(‘error message))}, 1000)),new Promise(resolve => setTimeout(() => {resolve(2)}, 2000)),]).then(res=>console.log(res)).catch(err = > console.log(err));

.allSetteled()

According to article : “Promise.allSettled gives you a signal when all the input promises are settled, which means they’re either fulfilled or rejected.”

let urls = [
"https://swapi.co/api/people/1/",
"https://swapi.co/api/planets/3/", "https://swapi.co/api/starships/9/"
];
let requests = urls.map(url => fetch(url));Promise.allSetteled(requests).then(responses => responses.forEach(response => console.info(response)));
//try it on your console and see what you get.

.race()

As the name of the function “race()”, it races among the promise and returns the promise that fulfills or reject as soon as one of the promise fulfill or reject.

Promise.race([new Promise(resolve => setTimeout(() => {resolve(1)}, 4000)), // 1new Promise(resolve => setTimeout(() => {resolve(2)}, 3000)), // 2new Promise(reject=> setTimeout(() => {reject(3)}, 2000)), // 3]).then(res=>console.log(res), err=>console.log(err));Result : 3 // promise 3 gets rejected first .

That’s all about Promise in JavaScript. I hope, I have covered all aspects of promise. To read more about its specifications and examples I recommend Mozilla developer network (MDN) .

--

--

Rajeev R
The Startup

A Javascript enthusiast , A web developer, A passionate cosmologist.