My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more

Implement Request Timeout Using Fetch and AbortController

Hanan Hamza's photo
Hanan Hamza
·Feb 10, 2021·

3 min read

consider this, you have a web-app that requests some data from some external service and you want to cancel the request if it takes more than n seconds. how would you implement this using javascript? I got you

this is the final snippet that you could modify according to your needs:

(async () => {

// we'll use to add dely/sleep logic
const timedOut = Symbol("Timeout")
const sleep= (delay) => new Promise((resolve, reject) => {
  setTimeout(resolve, delay, timedOut);
});

// the actual interface that we'd be using to cancel the request
const abortController = new AbortController();
const signal = abortController.signal;

// this is our external api call
// delay is added only to mock time-taking requests
const getData =async (signal,delay) => {
await sleep(delay)
return fetch("https://jsonplaceholder.typicode.com/todos/1",{
  signal
})
}

// promise.race returns whichever promise resolves first
const res = await Promise.race([
  sleep(3000),
  getData(signal,3000)
]);

// if response is timeout abort the request
if(res === timedOut) {
  abortController.abort();
} else {
  // do whatever you want to do with the result
}
})()

lets walk through the code bit by bit

const timedOut = Symbol("Timeout")
const sleep= (delay) => new Promise((resolve, reject) => {
  setTimeout(resolve, delay, timedOut);
});

this code resolves after however much delay we provide it with value of the symbol timedOut which we'll use later

const abortController = new AbortController();
const signal = abortController.signal;

this is the interface that allows us to cancel one or more webRequests that use the same signal

const res = await Promise.race([
  sleep(3000),
  getData(signal,3000)
]);

// if response is timeout abort the request
if(res === timedOut) {
  abortController.abort();
} else {
  // do whatever you want to do with the result
}

The Promise.race() method returns a promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise.

in our case, if the request takes more time than the timeout specified; sleep() function will resolve first and we can compare the response to abort the request.

That's all folks! :)