Understanding Promises in Node.js
Tags: node, javascript
Published: 2021-07-09 10:43:55

---
title: Understanding Promises in Node.js
published: true
date: 2021-03-24 00:00:00 UTC
tags: node, javascript
canonical_url: https://www.mariokandut.com/understanding-promises-in-node-js/
---

A promise is a placeholder for a value that will be available in the future, so the result of an asynchronous task can be handled once it has finished. Promises make writing asynchronous code easier and are an improvement to the callback pattern (please google for `callback hell`). Since ES6 promises are a standard part of Javascript and with `async/await` (ES8) they are used in async functions .

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#what-are-promises)What are promises?

To understand Promises it is important to understand the **difference between synchronous and asynchronous code** first.

Synchronous code executes in the sequence it is written, code statements wait until the ones before them have finished. Hence, **synchronous code is considered blocking in Node.js**. Blocking could be in some rare cases considered useful, like reading important configuration on start-up before anything else runs, but the application is unresponsive until this synchronous task is finished. Therefore, not applicable on long-running tasks, like making an HTTP call.

Asynchronous code works by starting a task, and letting it complete in the background while other code is still able to execute. When the async code has completed, the handler function (callback) is immediately executed with the result from the async code. Hence, **asynchronous code is non-blocking** , because it does not prevent the rest of your code from executing, while the asynchronous task is running in the background. With async code, we don't know when or if the task will complete successfully. The callback of the async code will be called as soon as the result is available, or when an error has occurred.

Once you an async process has started, like an HTTP request, filesystem access, or something similar, you are given something that will notify the caller when that process has completed. A Promise is that "something". **A promise is a placeholder for a value that will be available in the future.**

### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#why-use-promises)Why use Promises?

Promises allow to handle the results of asynchronous code, like callbacks. Unlike callbacks, the async code with promises is easier to read, maintain, and reason about. Consider these examples, five consecutive API calls with error handling.

**Promises**

```
fetch('url')
  .then(() => fetch('url'))
  .then(() => fetch('url'))
  .then(() => fetch('url'))
  .then(() => fetch('url'))
  .then(() => console.log('all done'))
  .catch(err => console.log(err));
```

**Callbacks**

```
fetchCallback('url', err => {
  if (err) return console.log(err);
  fetchCallback('url', err => {
    if (err) return console.log(err);
    fetchCallback('url', err => {
      if (err) return console.log(err);
      fetchCallback('url', err => {
        if (err) return console.log(err);
        console.log('all done');
      });
    });
  });
});
```

As you can see, the code is more legible with Promises.

### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#working-with-promises)Working with Promises

We can interact with the result of the Promise by chaining together handlers, that will either wait for the Promise to be fulfilled with a value, or rejected with the first error thrown.

```
fetch('url')
  .then(response => console.log(response.status))
  .catch(error => console.log(error));
```

In the above code example `fetch` returns a Promise, and the Promise API allows us to chain the `then` and `catch` handlers.

Your Promise chain should include a catch handler to deal with any Promises that are rejected in the chain. To handle errors with `catch` is best practice.

> In future versions of Node.js, unhandled Promise rejections will crash your application with a fatal exception.

A Promise is in one of these three states:

- **pending** : initial state, neither fulfilled nor rejected.
- **fulfilled** : the operation was completed successfully.
- **rejected** : the operation failed.

### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#creating-a-promise)Creating a Promise

A new Promise can be created by initializing one with the `Promise` constructor:

```
const myPromise = new Promise((resolve, reject) => {
  // do something asynchronous
});
```

The **Promise constructor** takes two functions as arguments, **resolve** and **reject**. We can do the asynchronous task, and then call either resolve (with the result if successful) or reject(with the error). The constructor returns a Promise object, which can then can be chained with `then` and `catch` methods.

Let's have a look at some example:

```
const fs = require('fs');

const myPromise = new Promise((resolve, reject) => {
  fs.readFile('example.json', (err, data) => {
    if (err) {
      reject(err);
    } else {
      resolve(data);
    }
  });
});

myPromise
  .then(data => console.log(data))
  .catch(err => console.log(err));
```

In the code example above, we wrapped `fs.readFile` in a `Promise`. If reading the file encountered an error, we pass it to reject, otherwise we pass the data obtained from the file to resolve. Calling `resolve` passes the data to our `.then` handler, and `reject` passes the error to the `.catch` handler.

### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#chaining-promises)Chaining Promises

Combining multiple Promises is one of the big advantages of Promises over using callbacks. It is difficult to orchestrate multiple callbacks together, whereas with Promises it is much more readable, and error handling is standardized between the different Promises.

Let's have a look at an example for fetching the [json placeholder API](https://jsonplaceholder.typicode.com/) to get some todos.

```
fetch('https://jsonplaceholder.typicode.com/todos')
  .then(response => response.json())
  .then(json => console.log(json))
  .catch(err => console.log(err));
```

In the example above we fetch some JSON data via an HTTP request. The `fetch` function returns a promise, which will either resolve or reject. The attached `then` handles the response by fetch, when it resolves. The response body has a `json` method for parsing the response from JSON to an object. The `json` method returns a promise of its own, which handle by attaching another `then` handler, and in case of error we attach a `catch` handler and log the error.

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#tldr)TL;DR

- Promises help deal with the execution flow of asynchronous code.
- Promises are cleaner and more maintainable than using callbacks (in most cases).
- A Promise can have one of three different states: pending, fulfilled, or rejected.
- We can chain `then` and `catch` methods to a Promise in order to execute code when the state changes.
- Promises can be used to execute synchronous operations without blocking the Node.js process.

Thanks for reading and if you have any **questions** , use the **comment** function or **send me a message** **[@mariokandut](https://www.twitter.com/mariokandut)**.

If you want to know more about **[Node](https://www.mariokandut.com/tags/node)**, have a look at these [Node Tutorials](https://www.mariokandut.com/tags/node).

### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#references-and-big-thanks)References (and Big thanks):

[HeyNode](https://heynode.com/tutorial/what-are-promises/),[MDN Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise),[MDN - Using Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)