JavaScript Best Practices — Promises
Tags: codequality, webdev, programming, javascript
Published: 2021-01-27 02:11:25

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

Some ways of writing JavaScript code are better than others.

In this article, we’ll look at best practices for using the latest JavaScript promise features.

* * *

### Converting Non-Promise Async Code to Promises

We can convert the non-promise async code to promises with the `util.promisify()` method. This lets us convert many functions with async callbacks with the signature of the form `(err, res)`, where `err` is an object with errors and `res` has the results of the async code.

Any function that has a promising form defined for it can also use this utility to return the promise form. As long as the promise version is stored as the value of the symbol property `util.promisify.custom` , we can get the promise version.

For instance, since `setTimeout` has a promise-based version in the standard library of Node.js, we can convert it to a promise as follows:

```
const util = require('util');
const sleep = util.promisify(setTimeout);

(async () => {
  await sleep(1000);
  console.log('slept');
})()
```

Now we have a `sleep` function that pauses execution for the time we want, instead of having to nest callbacks.

* * *

### Asynchronous Chaining

In the old way, we chain promises with the `then` method.

For instance, we write:

```
promise1
  .then((res) => {
    //...
    return promise2
  })
  .then((res) => {
    //...
    return promise3
  })
  .then((res) => {
    //...
  })
```

We can clean this up with `async` and `await` as follows:

```
(async () => {
  const val1 = await promise1;
  //...
  const val2 = await promise2;
  //...
  const val3 = await promise3;
  //...
})();
```

This is much cleaner as the resolve promise values are assigned to the constants or variables on the left side.

* * *

### Using Catch to Catch Errors

As with synchronous code, we have to catch errors and handle them gracefully.

To do that with promise code, we can call the `catch` method. For instance:

```
promise1
  .then((res) => {
    //...
    return promise2
  })
  .then((res) => {
    //...
    return promise3
  })
  .then((res) => {
    //...
  })
  .catch((err) => {
    //...
  })
```

If we use `async` and `await` , then we use `try...catch` as we do with synchronous code, as follows:

```
(async () => {
  try {
    const val1 = await promise1;
    //...
    const val2 = await promise2;
    //...
    const val3 = await promise3;
    //...
  } catch (ex) {
    //...
  }
})();
```

The code in `catch` in both examples would run when the first promise is rejected.

* * *

### Use Finally to Run Code That Should Run Regardless of the Outcome of the Promises

If we need to run code that should be run regardless of the outcomes of the promise chain, then we should use the `finally` method or the `finally` block for async and await code.

For instance, we can run clean up code in `finally` as follows:

```
promise1
  .then((res) => {
    //...
    return promise2
  })
  .then((res) => {
    //...
    return promise3
  })
  .then((res) => {
    //...
  })
  .finally((err) => {
    //...
  })
```

Or we can write:

```
(async () => {
  try {
    const val1 = await promise1;
    //...
    const val2 = await promise2;
    //...
    const val3 = await promise3;
    //...
  } catch (ex) {
    console.log(ex);
  } finally {
    //...
  }
})();
```

* * *

### Multiple Asynchronous Calls with Promise.all()

If we want to run multiple unrelated promises at once, then we should use `Promise.all`.

For instance, we can run them all at once as follows:

```
Promise.all([
    promise1,
    promise2,
    promise3,
  ])
  .then((res) => {
    //...
  })
```

If we use `async` and `await`, we can write:

```
(async () => {
  const [val1, val2, val3] = await Promise.all([
    promise1,
    promise2,
    promise3,
  ])
})();
```

In both examples, the resolved values of all three promises are either in `res` or assigned to an array on the left (in the second example).

This way, they run all at once instead of waiting for each to resolve.

* * *

### Summary

*   We can clean up our async code by using promises.
*   Converting to async code to promises can be done with Node apps by using the `util.promisify` method.
*   If we want to chain promises, before sure to add the `catch` method or block to handle errors gracefully.
*   `finally` method or block can be used to run code that’s always run regardless of the promises outcomes.
*   `Promise.all` is great for running unrelated promises all at once.