JavaScript promises, mastering the asynchronous

Magus
471.2K views

Open Source Your Knowledge, Become a Contributor

Technology knowledge has to be shared and made accessible for free. Join the movement.

Create Content

When you deal with promise chaining, you must avoid some traps.

The broken chain

Take the following code:

function test() {
    var promise = job();

    promise.then(function(data) {
        doSomething(data);
    });

    return promise;
}

In this code, we add a callback on the promise, then we return the promise. The problem is that we return the initial promise. Not the result of promise.then. The result of promise.then is a lost promise because no one can interact with it.

You should write this:

function test() {
    return job().then(function(data) {
        doSomething(data);
    });
}

Beware: Sometimes you must break the chain! For example, maybe doSomething is an asynchronous job but you don't want to slow the promise chain with it. Just be careful and be sure of what you are doing when you break a promise chain.

The pyramid of doom

You might be tempted to write something like this:

function test() {
    return job().then(function() {
        return job2().then(function() {
            return job3().then(function() {
                return job4().then(function() {
                    doSomething();
                });
            });
        });
    });
}

However, this code is wrong because the result of your function is job().then result. You broke the chain again. Use the promise chaining feature:

function test() {
    return job()

    .then(function() {
        return job2();
    })

    .then(function() {
        return job3();
    })

    .then(function() {
        return job4();
    })

    .then(function() {
        doSomething();
    });
}

The ghost promise

As a rule of thumb: When a function can return a promise, ALWAYS return a promise. Otherwise you'll have this ugly code everywhere:

function job() {
    if (test) {
        return aNewPromise();
    } else {
        return 42;
    }
}

var result = job();

if (typeof job === 'object' && typeof job.then === 'function') {
    // ...
} else {
    // ...
}

If you want to create an auto-resolved promise with a simple value, use Promise.resolve:

function job() {
    if (test) {
        return aNewPromise();
    } else {
        return Promise.resolve(42); // return an anto-resolved promise with `42` in data.
    }
}

If you want to create an auto-rejected promise, use Promise.reject.

The forgotten promise

You call a method that returns a promise but you create your own promise:

function test() {
    var promise = job();

    return new Promise(function(resolve, reject) {
        promise.then(function(data) {
            data = doSomething(data);
            resolve(data);
        }, function(error) {
            reject(error);
        });
    });
}

A lot of pointless code above. You can fix it like this:

function test() {
    return job().then(function(data) {
        return doSomething(data);
    });
}
Open Source Your Knowledge: become a Contributor and help others learn. Create New Content