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);
});
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"...}
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);
});
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();
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.
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();
Now if we run our code we see that we gracefully log our error:
DOMException: The user aborted a request.
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
Top comments (7)
Or we can just use the cross-platform solution (Demo):
Can I create multiple signals from the same instance of AbortController?
I don't believe so. We're not actually creating a signal but rater we're accessing the
signal
property of theAbortController
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 ofAbortController
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.
I guess that second edit would solve most cases I can think of. Thanks for sharing.
Yes, I can confirm that.
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:Um ... the code is cross-platform, so it works in node.js and browsers just in the same way.