Timeouts in Fetch calls using Javascript Promises

0 0
Read Time:2 Minute, 50 Second

Let’s see a quick example of how to have timeouts in fetch calls using JavaScript promises. By default the fetch() API does not have built-in support for timeouts. So we will build our custom solution in this example.

Why do you need timeout?

Well, it is a good idea to have a timeout in your API calls. Sometimes, it may happen that your API call response takes a lot of time to return. This can happen for various reasons but most commonly a slow server or slow network. In that case, you do not want your users to be waiting for long and your spinner spinning infinitely.

So a good approach is to have a timeout so that if the API call response does not return back within the defined period, you show a message to the user and maybe ask him to try again. At least the user now knows that something happened.

JavaScript Promise to our rescue

Since, there is no built-in support for timeout within fetch(), there is a clever little technique to achieve the same using JavaScript promises. The Promise API has a very useful method of race() which takes an array of promises and basically executes all of them asynchronously and simultaneously. The first promise that resolves or rejects is the winner and the overall race() method resolves with that.

Promise.race([promise1, promise2, ....]).then((data) => {
  //your code
}).catch((err) => {
  //your code
);

Full example

Here’s the full example based on the concept discussed above. There is always a scope of improvement. In case you have one, give me a shoutout in the comments section.

const timeout = 3000; //configure timeout time
const URL = 'https://reqres.in/api/users'; //?delay=4

//time out promise
const timeoutPromise = new Promise((resolve, reject) => {
  //reject the promise after the timeout
  setTimeout(() => reject('timed out'), timeout);
});

//make the API call
//returns a promise
async function makeAPICall(url) {
  const resp = await fetch(url);
  return await resp.json();
}

//race between 2 promises
//which promise resolves or rejects first
//the 2 promises will execute parallally
Promise.race([makeAPICall(URL), timeoutPromise]).then((data) => {
  console.log(data); //json response
}).catch((err) => {
  console.log(err); //rejected
});

You can play with the example by adding a delay in the API call and check if the timeout works fine. And vide versa.

Code explanation

I will not go into much details as it is quite self-explanatory and simple. But the basic idea is that the makeAPICall() function returns a promise that. resolves with the json() response. And then we have the timeout promise defined which is just a promise instance that rejects after the timeout specified. Now we have both defined inside the Promise.race() method. So as soon as the code executes, it starts a race between the 2 promises. If the makeAPICall() resolves first, then the overall promise resolves with the json() response. However, if the timeout promise rejects first (before the API response is back), then the overall promise is rejected with the message. Which you can then handle inside the catch() block.

Give it a try. Here’s the CodeSandbox link with the full code – https://codesandbox.io/s/fetch-timeout-using-promise-h07bg

Cheers!

In case you are looking at how to cancel an API call made using fetch() then you may read this post.

Happy
Happy
0 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleepy
Sleepy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %