×
☰ See All Chapters

JavaScript ES6 Promises

One disadvantage of web development is the constant need to wait—wait for the user to take an action, wait for the server to respond to a request, wait for the database to sort its records. Rather than halt the application, it's more efficient to assign a routine to process results as they become available. This frees the application to work on other tasks instead of waiting. The technique of assigning a routine to be executed at an indeterminate time is called asynchronous programming.

If an application needs data that isn't available right now, it may receive a promise. A promise is a data structure that represents an operation that hasn't completed yet but is expected to provide a result.

States of a promise

At any time, a promise can be in one of these three states –

  1. Pending: A promise is pending when you start it. It hasn’t been resolved or rejected. It is in a neutral state. 

  2. Fulfilled: When the operation is successful, a promise is considered fulfilled or resolved. 

  3. Rejected: If an operation fails, the promise is rejected. 

Creating a Promise

const promise = new Promise((resolve, reject) => {

    // Do some async stuff and get

    // If async operation successful then call resolve function

    resolve();

    // If async operation fails then call reject function

    reject();

});

We create an instance of a promise by calling new on the Promise class. The promise class constructor takes one function argument. That function, in turn, has two arguments – resolve and reject. We should call resolve function if the async operation is successful and call reject function if the async operation fails. Since we are defining the function, we can name arguments resolve and reject whatever we want but the convention is to call them resolve and reject. Promise serves the same function as callbacks but has a nicer syntax and makes it easier to handle errors. Promises are not asynchronous, but we can make them asynchronous by calling resolve/reject in callbacks of other asynchronous call.

Promises are not callbacks for any asynchronous operations, promises uses callbacks from other asynchronous operations, the reason we use promises is to have nicer syntax. If you are doing single asynchronous operations multiple times and have different response and error handlers for each operation then we can use one promise defined for all those multiple calls. A few problems exist with callbacks. One is known as "Callback Hell". A larger problem is decomposition. The callback pattern requires us to specify the task and the callback at the same time. In contrast, promises allow us to specify and dispatch the request in one place. Also, by using promises we can attach multiple handlers to the same task which we cannot do by callbacks.

Promise Example

// JavaScript source code

var isOperationSuccsess = true;

const myPromise = new Promise(function(myResolve, myReject) {

    setTimeout(function() {

        if (isOperationSuccsess) {

            myResolve("Promises resolved to success");

        } else {

            var reason = new Error('Promises failed');

            myReject(reason);

        }

 

    }, 3000);

});

 

var testPromise = function() {

    myPromise

        .then(function(value) {

            console.log(value);

        })

        .catch(function(error) {

            console.log(error.message);

        });

};

testPromise();

Let's run the example and see the result!

javascript-es6-promises-0
 
javascript-es6-promises-1
 

Instantly resolve or reject promises

Calling resolve and reject is optional. Using the Promise.resolve(data) or Promise.reject(error) methods you can resolve or reject a promise immediately.

let firstPromise = Promise.resolve(100);

let secondPromise = Promise.reject(Error('error occured'));

 

firstPromise

    .then(console.log)

    .catch(console.log);

 

secondPromise

    .then(console.log)

    .catch(console.log);

 

 Output:

javascript-es6-promises-2
 

Chaining Promises

var isOperationSuccsess = false;

 

const myFirstPromise = new Promise(function(myResolve, myReject) {

    setTimeout(function() {

        if (isOperationSuccsess) {

            myResolve('Message from first Promise');

        } else {

            var reason = new Error('Promises failed');

            myReject(reason);

        }

 

    }, 3000);

});

 

var mySecondPromise = function(value) {

    var message = 'Message from second Promise';

    return Promise.resolve(message);

};

var myThirdPromise = function(value) {

    var reason = new Error('Promises failed from third promise');

    return Promise.reject(reason);

};

 

var testPromise = function() {

    myFirstPromise

        .then(mySecondPromise)

        .then(function(value) {

            console.log(value);

        })

        .catch(myThirdPromise)

        .catch(function(error) {

            console.log(error.message);

        });

};

testPromise();

javascript-es6-promises-3
 
javascript-es6-promises-4
 

Executing all promises

Using the syntax Promise.all(arrayOfPromises), you can execute an array of Promises. This method resolves when all promises have resolved and fails if any of those promises fail.

let firstPromise = Promise.resolve(100);

let secondPromise = Promise.resolve(200);

let thirdPromise = Promise.resolve(300);

 

Promise

    .all([firstPromise, secondPromise, thirdPromise])

    .then(values => {

        console.log(values);

    });

The output for the code above would be [100, 200, 300]; Promise.all() has fail fast behavior. This means that as soon as any one promise fails, Promise.all will reject immediately.

Promise race function

You can use the Promise.race(arrayOfPromises) function when you want the value of the first promise that resolves or rejects.

let promise1 = new Promise((resolve, reject) => {

    setTimeout(resolve, 2000, 'promise 1 resolved');

});

 

let promise2 = new Promise((resolve, reject) => {

    setTimeout(reject, 3000, 'promise 2 rejected');

});

 

Promise

    .race([promise1, promise2])

    .then(console.log)

    .catch(console.log);

 

In the example above, the .then() function would be invoked because promise1 resolves before promise2 even though promise2 fails. The output would be "promise 1 resolved";

 


All Chapters
Author