Skip to main content

Command Palette

Search for a command to run...

Promises in JavaScript

Published
•7 min read•View as Markdown
Promises in JavaScript

JavaScript provides a concept of "Promises" for handling the asynchronous calls.

Let's understand the details of "Promises in JavaScript" by covering the following topics in this article.

  • What are Promises in JavaScript?
  • How to create a Promise in JavaScript.
  • How do Promises work in JavaScript?
  • Why and When to use Promises in JavaScript?
  • How to consume a Promise in JavaScript?
  • Key Takeaways

What are Promises in JavaScript?

Promises are JavaScript objects that represent an eventual completion or failure of an asynchronous operation.

In simple, A Promise in JavaScript is an object that holds the future value and state of an asynchronous operation.

For example, if we are requesting some data from a server, the promise promises us to get that data that we can use in the future and the state of that promise whether it is fulfilled or rejected or still in pending state.

A promise object can have the following states:

  • Pending: It is an initial state, where the result is not ready, and it is waiting for the asynchronous operation to get finished.

  • Resolved/Fulfilled: It means that performed action completed successfully. i.e., function returned promised value.

  • Rejected: It means that performed action failed or an error occurred. i.e., function did not return the promised value.

How to Create a Promise in JavaScript?

As we discussed above, A Promise in JavaScript is an object representing the eventual completion or failure of an asynchronous operation. Its syntax looks like below:

Syntax:

const promise = new Promise(function(resolve,reject){
//do something

});

Note: We create a new promise using the Promise constructor, which takes a single argument, a callback function, also known as executor function, which in turn takes two callbacks functions, resolve, and reject.

The executor function immediately executes when a promise creates. The promise resolves by calling the resolve() method and is rejected by calling the reject() method.

How Promises works in JavaScript

To understand how exactly promises works, let us take the example, Consider you are making a promise to your mother saying that you are going to clean up your room by the end of the day. So two possible things can happen either you will be going to clean the room, or you are going not to clean the room and break your promise. Let's write that promise in the JavaScript.

let promiseCleanRoom = new Promise(function(resolve,reject){  
    cleanRoom = true;  
    if(cleanRoom){  
      resolve('Cleaned the Room');   
    }else{ 
      reject('Broke the promise');  

    }  
});

The above code block shows how to create the promise. i.e., when this promise executes, then it will give either resolve status or reject status based on the cleanRoom value.

Now, lets invoke the above promise

promiseCleanRoom.then((result)=>{  
      console.log(result)
  })

In the above snippet, it shows how to utilize the created promise, and there is ".then", a method that will perform some of the action only when a given promise is fulfilled or resolved. In this case, it will print the result sent by promise when it resolves, i.e., Cleaned the Room

There is one more case that will happen if the promise got broken or some error occurred in that case. Then we can use the ".catch" block that will allow handling the broken or instances of error.

promiseCleanRoom.then((result)=>{  
      console.log(result)   
}).catch((result)=>{   
   console.log(result) //will execute if promise is rejected or errored out
})

Suppose, if the promise breaks, then it will execute the catch block by skipping the then block, and output will be "Broke the promise".

Why and when to use Promises in JavaScript

Before we discuss on when and why we use promises, we need to know about callbacks.

callback functions used to handle the asynchronous execution, these callbacks indicates the operation that JavaScript has to execute on successful completion of an asynchronous operation.

In simple, A callback is a function that is passed as an argument to another function that executes the callback based on the another function result. They are basically functions that are executed only after a result is produced.

Here is the simplest example of a callback function:

function exec_2sec(callback) {
    return setTimeout(() => {
        console.log('2nd callback took 2 seconds to execute')
        callback();
    }, 2000);

}

function exec_3sec() {
    return setTimeout(() => {
        console.log('3rd callback took 3 seconds to execute')
    }, 3000);
}

function exec_1sec(callback) {
    return setTimeout(() => {
        console.log('1st callback took 1 second to execute')
        callback(exec_3sec);
    }, 1000);
}

function run (){
    exec_1sec(exec_2sec);
}

run();

These callbacks has a disadvantage during nested callbacks which leads to "callback hell".

Callback Hell: Callback Hell is essentially nested callbacks stacked below one another forming a pyramid structure. Every callback depends/waits for the previous callback, thereby making a pyramid structure that affects the readability and maintainability of the code.

So this callback hell can be handled by promises, as promise is a object where you can attach callbacks, instead of passing callbacks into a function.

Promises makes a way to avoid callback hell is that you can chain multiple .then() on each other which avoid nested callbacks and a neater line of code.

Above example using promises.

function exec_2sec() {
    return new Promise((resolve,reject)=>{
        setTimeout(() => {
            resolve('2nd callback took 2 seconds to execute')
        }, 2000);
    });

}

function exec_3sec() {

    return new Promise((resolve,reject)=>{
        setTimeout(() => {
            resolve('3rd callback took 3 seconds to execute')
        }, 3000);
    });
}

function exec_1sec() {
    return new Promise((resolve,reject)=>{
    setTimeout(() => {
        resolve('1st callback took 1 second to execute')
    }, 1000);})
}

function run (){
    exec_1sec()
    .then((result)=>{console.log(result); return exec_2sec();})
    .then((result)=>{console.log(result); return exec_3sec();})
    .then((result)=>{console.log(result)})
}

run();

How to consume a promise in JavaScript?

Promises consume by registering functions using .then, .catch, and .finally methods. A Promise object serves as a link between the executor and the consuming functions, which will receive the result or error, and the consuming functions can use any of the .then, .catch, or .finally methods.

How to use .then() as a consumer function?

The .then() method invokes when a promise is either resolved or rejected. Its syntax looks like below:

Syntax

.then(function(result){  
        //statements when the promise is resolved successfully  
    }, function(error){  
        //statements when the promise was rejected or raised an error  
    })

Let comprehend in this way, assume an if-else statement where code in the if block will execute when the given condition is true; otherwise, it will execute the else block. Similarly, the "then" method will take two functions as parameters where the first function will run when a promise resolves successfully, or it will execute the second method when a promise rejects or raise an error.

function exec_2sec(arg) {
    return new Promise((resolve,reject)=>{
       if(arg==="pass")
        resolve("passed successfully")
       else
        reject("sorry failed");
    }); 
}

function run (arg){
    exec_2sec(arg)
    .then((result)=>{console.log(result);},(error)=>{console.log(error);})
}

run("pass");
run("fail");

But passing two functions as parameters for then method looked somewhat confusing. Therefore, to overcome this, the ".catch" block or function was introduced where the catch block will explicitly handle when there is rejection, or some error has occurred.

How to use .catch() as a consumer function?

The .catch() method invokes when a promise rejects, or some error occurs in the execution. Its syntax looks like below:

syntax

.catch(function(error){  
        //Statements to handle error raised  
    })

Lets under the usage and implementation of the ".catch()"

function exec_2sec(arg) {
    return new Promise((resolve,reject)=>{
       if(arg==="pass")
        resolve("passed successfully")
       else
        reject("sorry failed");
    }); 
}

function run (arg){
    exec_2sec(arg)
    .then((result)=>{console.log(result);})
    .catch((err)=>{console.log(err)})
}

run("pass");
run("fail");

How to use .finally() as a consumer function?

As we used to have the finally block in a regular try{...} catch{...} of exception handling, there’s finally in promises also. This consumer function always executes when the promise settles: be it resolve or reject. The finally block a good handler for performing cleanup actions, which we always expect to execute. Its syntax looks like below

.finally(() => {  
 // Statements which are expected to be executed always
})

How to use Promise.all() as a consumer function?

If you want to execute multiple promises in parallel and want to wait for the completion of all the promises before proceeding further, you can use the ".all" function provided by the Promises in JavaScript. It takes an array of promises function and executes all functions simultaneously/parallelly and wait until all promises are either resolve or reject. Its syntax looks like below:

Promise.all([array of promises]);

Note : Promise.all() doesn't ensure any ordering of promises. It just executes all of the promises in parallel.

How to use Promise.race() as a consumer function?

If you want to execute multiple promises in parallel but don't want to wait for the completion of all the promises before proceeding further, you can use the ".race" function provided by the Promises in JavaScript. It just waits for completion of any one promise, which returns first. It will take an array of promises function and execute all functions simultaneously and wait until any one of the promises is either resolve or reject. Its syntax looks like below:

Promise.race([array of promises])

Key Takeaways

  • Promises can handle the asynchronous calls in JavaScript.
  • Promises avoid the problem of "callback hell", which happens due to nested callback functions.
  • A promise will be "pending" when executed and will result in "resolved" or "rejected", depending on the response of the asynchronous call.