Chaining Promises in JavaScript

Monday, September 28, 2015

In part 1 we looked at the basic use of native promises in JavaScript 2015. In this post we'll look at how to compose and chain promises.

Chaining promises can make asynchronous code flow synchronously. For example, consider the following calculate method which delivers a result using a promise.

let calculate = function (value) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(value + 1);
        }, 0);
    });
}; 

Imagine you need to invoke the calculate method four times, and each time you invoke calculate you need to pass the result from the previous call into the next call (this would simulate HTTP APIs where you need to make multiple requests, all dependent on one another, to fetch all of data required for a page). With promises, the series of method calls could look like the following.

calculate(1)
    .then(calculate)
    .then(calculate)
    .then(calculate)
    .then(verify);

function verify(result) {
    expect(result).toBe(5);
    done();
};

The above code also verifies (with Jasmine) that the final result is the value 5, because compute will add 1 to the result on each invocation. The code works because each call to the then method of a promise will result in a new promise. You might think this happens because the calculate method returns a new promise, but a new promise will appear even if the function passed to the then method doesn’t explicitly produce a promise. As an example, let’s replace one call to calculate with an arrow function that simply returns result + 1.

calculate(1)
    .then(calculate)
    .then(result => result + 1)
    .then(calculate)
    .then(verify);

function verify(result) {
    expect(result).toBe(5);
    done();
};

The result of the above code is still the value 5, and the object returned from the then call with an arrow function is still a promise, because the then method ensures that the success handler’s return value is wrapped into a promise. If the success handler does not return a value, the new promise will deliver the value undefined to the next handler.

To see how easy it is to create a new promise when you already have a value to resolve the promise, let’s look at the promise API in tomorrow's post.


Comments
gravatar Graham Tuesday, October 6, 2015
I find the problem is that later promises often require both the output of the previous promise, and of an earlier one too. So I still end up with the arrowhead :( I could return an object with all the dependencies on it, but that doesn't feel very good either.
Comments are closed.

My Pluralsight Courses

K.Scott Allen OdeToCode by K. Scott Allen
What JavaScript Developers Should Know About ECMAScript 2015
The Podcast!