Simplifying Promises in JavaScript

JavaScript promises are easy to overcomplicate. Keep them simple and avoid writing unnecessary code.

ES2017’s async/await syntax is already widely adopted among JavaScript developers, but working with promises directly and cleanly is a necessary underlying skill.

Avoid Redundant Promise Construction

Here we have an unnecessary promise being created to wrap the result of a fetch():

function getDataAsync(url) {
    return new Promise((resolve, reject) => {
        const data = fetch(url).then(response => response.json());
        resolve(data);
    });
}

Because fetch itself is a function that returns a Promise, there’s no need to create a new Promise wrapping its result. The result is already resolved through an existing Promise. We can instead reuse the existing Promise returned from the fetch call:

function getDataAsync(url) {
    return fetch(url).then(response => response.json());
}

Whenever we’ve given a Promise, we can use the Promise we’re given. Following from this principle, note that Promise.then() itself returns a Promise. Even when we return this resulting Promise from a function we’ve implemented, we can continue chaining onto it with subsequent then() and catch() calls.

Take an Opportunity to Simplify

Constructing a Promise is fairly complex. We first need to pass the Promise constructor a function that can accept two callbacks — commonly known as resolve and reject, then implement some functionality and resolve on success or reject with an error. Not only is this a good amount to mental overhead, it also involves a certain amount of of syntactic baggage surrounding the functionality we care about.

In the following example, we create a Promise to simulate the act of getting data over a network. Instead of using an existing API that returns a Promise for us, we really do need to create our own:

function getMockDataAsync(shouldSucceed) {
    return new Promise((resolve, reject) => {
        if (!shouldSucceed) {
            reject(new Error('An error occurred.'));
        }
        resolve({ foo: 'bar' });
    });
}

However, there’s a simpler way to create a Promise that immediately resolves or rejects:

function getMockDataAsync(shouldSucceed) {
    if (!shouldSucceed) {
        return Promise.reject(new Error('An error occurred.'));
    }
    return Promise.resolve({ foo: 'bar' });
}

Promise.resolve() and Promise.reject() are static methods on the Promise class that return a Promise and resolve or reject it. These methods are pleasant to use compared to constructing a Promise manually.

  • Simplifying Promises in JavaScript
    • 2016
    • Front-End
    • Server-Side

Related Articles