JavaScript Promises. Part 3 — Promise Chaining

Abdu Manaz C A
Nerd For Tech
Published in
6 min readApr 26, 2021

--

Photo by Aida L on Unsplash

In parts 1 and 2 of this series, we understood Why promises were introduced, What promises are, and how to create them. In this part, we will build on that by understanding how we can chain multiple promises together or simply Promise chaining.

This is an important concept to understand, one which is at the base of further asynchronous JS concepts like async/await.

Up until this point, we have only talked about a single asynchronous task being carried out. But what if, we have to do multiple asynchronous tasks in succession, each after the previous one finishes?

To understand that, we have to be absolutely clear about one thing

Any value returned from a promise’s handlers will be wrapped as a promise

This means, if we return a value from a promise handler like — then, catch or finally, it will be wrapped as a promise.

Let's try an example. Try writing the below code excerpt in the console.

Try logging the variable secondObjectin the console, to check its type. You will get the below output

From this example, it is clear, that the secondObject is not a number and is in fact a promise, reiterating our earlier point:

Any value returned from a promise’s handlers will be wrapped as a promise

Then, how do we consume the promise returned from the handler? Simple. Like we consume any other promises — with the then/catch/finally handlers.

So, if we want to get the value 2 from the previous example, apply another then handler to the promise secondObject or better yet, simply add the new then handler to the previous then handler like below

Now 2 will be printed.

This process of chaining multiple promises together is termed as Promise Chaining.

Using Promise Chaining, we can handle multiple successive asynchronous operations as each handler will only be executed once its immediate predecessor completes.

Let's look at a real-world example.

Consider you are building a social media application where users can create posts, add comments to it. Kind of like Facebook. But not toxic :D. As an admin user, you want to see all the users in the system and all the posts by the first user in your dashboard.

You have to do 2 things in succession:

  1. Fetch all the users
  2. Fetch all the posts associated with the first user

We will use the fetch API to make the HTTP Requests and we will use `https://jsonplaceholder.typicode.com/` as the API provider for this example.

To fetch all the users we can use the code below

Pretty normal stuff. We pass the URL to retrieve a list of users to the fetch method. fetch makes the network call and returns a promise, which we access using the then handler.

But notice how we use promise chaining here itself.
This is because, the response from fetch API will be of type Response.
To extract the JSON body content from the response, we use the .json() method which returns a promise, wrapping the JSON body. So our users Array will be available in the 2nd then handler.

Now let's take a look at the code to access the different posts by a user

Similar to the previous code. The only difference being the use of implicit return in arrow functions.

Now we have two separate promise chains that do 2 different asynchronous operations. We need to combine them together to achieve our goal. How do you do that?

In our second then handler we are returning the fetch operation to fetch posts by the user(line no 6). By using this simple step, we are chaining and executing multiple asynchronous operations in succession.

Error Handling

What if something goes wrong? How do you handle errors in Promise chaining?

Remember in the 2nd part of this series, we have touched upon it. Go check it out if you haven’t already.

Whether to use a catch block, or handle the error in then block, depends on our requirements and whether the promises are chained together. We will be diving into Promise chaining in the next section. For now, just remember that it is possible to handle the error in then block itself.

In a promise chain, if an error occurs in a then block, it can be handled in the failure handler of a following then block or in a following catch block. But which should you choose? It depends on the answer to the question

Should the error break the entire promise chain ?

If the error shouldn't break the chain, handle the error in one of the following then blocks.
If the error should break the chain, don’t add a failure handler in the then block and instead provide a catch block.

Lets see both in action

First, let’s produce an error. Replace the URL in our previous promise chain with a non-existent URL. So that the initial fetch itself fails. Execute the code. You will get the following error.

We haven’t handled the error, so after the error occurs, no then handlers are executed.

Now let’s handle the error.

Handle Error by NOT Breaking the Promise Chain

If an error occurs while fetching the users, then instead of fetching the posts by the first user, you want to fetch all the posts in the system. In other words, we want the promise chain to resume from a certain point if an error occurs prior to that. How do you do that?

We add a function (line no 7) to handle the error case to the 2nd then (line no 3) in the chain.

If you observe, the error is not handled in the immediate then block. Meaning, If an error occurs in a promise chain (while fetching the users in our case), the error will be propagated through the chain until it reaches the error handling function (if any), which then gets executed and normal chain execution resumes.

Execute the code and you will see normal chain execution resumed.

Handle Error by Breaking the Promise Chain

But what if we don't want any block to be executed once an error occurs?
To do that, add a catch block to the end of the chain which will act as a global error handler for the promise chain.

Here, we are using a catch block at the end of the chain to handle any error in the promise chain.

Execute the code and you will see the chain broke once the error occurred.

In this article, we learned what Promise chaining is, how to chain promises together, and the different error handling methods in promise chaining.

If you have found this article helpful, make sure to clap and share it with your friends. If you have any suggestions/comments let me know. Make sure to follow me as we will be building on this by understanding the different promise methods Promise.any() , Promise.all() as well as async/await.

--

--