Chain HTTP Requests in React Using Promises
Sep 23, 2020 • 5 Minute Read
Introduction
It is almost guaranteed that as a developer on any modern React app you will need need to make HTTP requests that depend on the response of previous requests. Maybe your app needs to request a list of transactions once a user's account information has been requested. In cases like these, you need to chain these HTTP requests together so that they happen one after the other. In modern JavaScript, you can easily chain HTTP requests using Promises. In this guide, you will learn how to use raw, Promise syntax and the new async/await keywords to chain HTTP requests.
Let's dive in!
Chaining Requests Using Promises
Building on the previous example, let's say you are creating a React component that needs to display a batch of transactions for a given account. Because of how the API is structured, you have to make, at a minimum, two HTTP requests to complete this feature. First, you must request the account, and then you have to use a batch ID from the response in order to request the transactions that you need to display in the UI.
You can easily complete this feature by using the Fetch and Promise APIs. The below code is an example of how you might write the code for successive HTTP requests in a way that uses Promise-chaining syntax.
reqAccountAndTransactions = () => {
const accountInfoReq = fetch(`http://localhost:3000/api/account/${accountId}`).then(res => res.json())
accountInfoReq.then(accountInfo => {
// We can now store account info state on this component
return fetch(`http://localhost:3000/api/transaction/${accountInfo.transactionBatchId}`)
})
.then(res => res.json())
.then(transactions => {
// Here we can use our transaction data
})
.catch(reqErr => console.error(reqErr))
...
}
And there you have it! In the above code, first you are creating an account info request using Fetch to ensure that you call the .json() function available on returned responses when using the Fetch API. Note that this code, because it is asynchronous, doesn't completely execute before you start requesting transactions. Because of this, you can take this accountInfoReq variable, which is a Promise, and chain it together with a new request for transactions. You can see how you would use the underlying accountInfo data to construct a new request for transactions.
This is the power of Promise chaining. By chaining Promises together, you can not only guarantee that one Promise will complete directly after the others prior to it are completed, but you can also use just a single .catch to catch any errors that may occur in all of the requests. This is powerful, and is a great means of staying away from a horribly nested code.
This is great, but in the next section, you will see how we can streamline the above code to make it even more readable.
Chaining Requests Using Async/Await
With the advent of new language features, JavaScript has become a powerful language in any developer's tool belt. One of these new language features is async/await.
You can think of async/await syntax in JavaScript as syntactic sugar on top of the Promise API. By using async/await, you can write asynchronous code in a synchronous manner. This is incredibly powerful because asynchronous code is notoriously hard to read. Being able to write asynchronous code in a synchronous and imperative way allows you to write more maintainable code that is easy to read. Below you can see the same code written above, but refactored to use async/await syntax.
reqAccountAndTransactions = async () => {
const accountInfo = await fetch(`http://localhost:3000/api/account/${accountId}`).then(res => res.json())
// We can now store account info state on this component
const transactions = await fetch(`http://localhost:3000/api/transaction/${accountInfo.transactionBatchId}`)
.then(res => res.json())
// Here we can use our transaction data
...
}
Wow, you just about cut your code in half by making this change. As you can see, this code is much more readable and accomplishes the same thing. Under the hood, you are still using Promise chaining to achieve the desired result, but async/await abstracts away a lot of the implementation details for you. It is highly recommended that, when possible, you use async/await syntax in your React app while chaining HTTP requests.
Conclusion
Promises can allow you to easily chain asynchronous actions together. This is a much-needed capability in most React apps, so knowing how to create your own Promises along with using async/await syntax will set you up for success.
If you are looking to expand your knowledge even more when it comes to methodologies for chaining asynchronous actions, check out the RxJs library. RxJs is a library that helps you manage asynchronous actions via an Observable API.
I hope that this guide makes you feel confident when it comes to chaining HTTP requests and other asynchronous actions in your React apps. To learn more about Promises, please check out the Promise documentation.