DEV Community

loading...
Cover image for How to Abort a Fetch Request in JavaScript using AbortController

How to Abort a Fetch Request in JavaScript using AbortController

nas5w profile image Nick Scialli (he/him) Originally published at typeofnan.dev ・2 min read

Sometimes it's necessary to abort a fetch request. In this post, we explore how to quickly do so using AbortController!


If you enjoy this tutorial, please give it a 💓, 🦄, or 🔖 and consider:

📬 signing up for my free weekly dev newsletter
🎥 subscribing to my free YouTube dev channel


A Simple Fetch Request

Let's start out with a simple fetch request. We'll grab some metadata about my Github account and log it to the console.

fetch('https://api.github.com/users/nas5w')
  .then(res => res.json())
  .then(data => {
    console.log(data);
  });
Enter fullscreen mode Exit fullscreen mode

If we check our console, we see a json object describing my account has been logged. Here's a bit of that data.

{"login":"nas5w","id":7538045,"node_id":"MDQ6VXNlcjc1MzgwNDU=","avatar_url":"https://avatars2.githubusercontent.com/u/7538045?v=4","gravatar_id":"","url":"https://api.github.com/users/nas5w","html_url":"https://github.com/nas5w"...}
Enter fullscreen mode Exit fullscreen mode

Using AbortController

In this same scenario, we can create a new instance of the AbortController object and pass fetch a reference to the AbortController instance's signal object.

Here's what I mean:

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

fetch('https://api.github.com/users/nas5w', { signal })
  .then(res => res.json())
  .then(data => {
    console.log(data);
  });
Enter fullscreen mode Exit fullscreen mode

So now, fetch has a reference to the signal object on our controller instance. We can abort our fetch by calling abort on our controller:

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

fetch('https://api.github.com/users/nas5w', { signal })
  .then(res => res.json())
  .then(data => {
    console.log(data);
  });

controller.abort();
Enter fullscreen mode Exit fullscreen mode

If we run this, we no longer log the returned data because we have immediately aborted our fetch request!

Handling the Cancellation

You may have noticed in our last code snippet that our fetch request isn't gracefully aborted, we actually see an error in our console:

Uncaught (in promise) DOMException: The user aborted a request.
Enter fullscreen mode Exit fullscreen mode

In order to handle this cancellation error, we simply need to catch our error:

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

fetch('https://api.github.com/users/nas5w', { signal })
  .then(res => res.json())
  .then(data => {
    console.log(data);
  })
  .catch(err => {
    console.log(err);
  });

controller.abort();
Enter fullscreen mode Exit fullscreen mode

Now if we run our code we see that we gracefully log our error:

DOMException: The user aborted a request.
Enter fullscreen mode Exit fullscreen mode

So now we have successfully aborted our fetch request and caught the associated error.

A Note on Browser Compatibility

Most modern browsers have full support for AbortController but (of course) if you have to support IE you're out of luck! Be sure to check out the associated MDN docs for full compatibility info.


If you enjoy this tutorial, please give it a 💓, 🦄, or 🔖 and consider:

📬 signing up for my free weekly dev newsletter
🎥 subscribing to my free YouTube dev channel

Discussion (9)

Collapse
digitalbrainjs profile image
Dmitriy Mozgovoy • Edited

Or we can just use the cross-platform solution (Demo):

import cpFetch from "cp-fetch";

const promise1 = cpFetch("https://api.github.com/users/nas5w")
  .timeout(10000)
  .then((res) => res.json())
  .then(console.log, console.warn);

setTimeout(() => promise1.cancel(), 10);
Enter fullscreen mode Exit fullscreen mode
Collapse
hjorthbjorn profile image
Björn Hjorth

Can I create multiple signals from the same instance of AbortController?

Collapse
nas5w profile image
Nick Scialli (he/him) Author • Edited

I don't believe so. We're not actually creating a signal but rater we're accessing the signal property of the AbortController instance.

Edit: Here's the spec! Can confirm that the signal property is a boolean so we're really just talking one signal. You'd likely need another instance of AbortController if you're looking to potentially cancel multiple requests.

Edit 2: I could imagine, though, that you might want to cancel multiple http requests at the same time, in which case you could use the same signal to tell each fetch request to abort and that would work well.

Collapse
hjorthbjorn profile image
Björn Hjorth

I guess that second edit would solve most cases I can think of. Thanks for sharing.

Thread Thread
zhnedyalkow profile image
Zhitomir Oreshenski

Yes, I can confirm that.

digitalbrainjs profile image
Dmitriy Mozgovoy • Edited

Probably no, unless you mean that bundling the frontend of your app with webpack requires node.js. But the building process is in no way associated with Web servers. If you need to use it in old-school way directly without building, just import the UMD browser module as a script:

<script src="https://unpkg.com/cp-fetch/dist/cp-fetch.umd.js"></script> 
<script>
const promise1 = cpFetch("https://api.github.com/users/nas5w")
  .timeout(10000)
  .then((res) => res.json())
  .then(console.log, console.warn);

setTimeout(() => promise1.cancel(), 10);
</script>
Enter fullscreen mode Exit fullscreen mode
Collapse
digitalbrainjs profile image
Dmitriy Mozgovoy

Um ... the code is cross-platform, so it works in node.js and browsers just in the same way.

Forem Open with the Forem app