
Aborting a fetch request
February 9, 2020 • 3 min read • Tweet
tldr: AbortController is used to abort a fetch request. Check out this demo.
As of today, there are two primary ways to make a request in the browser. XMLHttpRequest and fetch.
XMLHttpRequest existed in browsers for a long time. the fetch was introduced with ES6.
XMLHttpRequest was always abortable. An abortable XHR request looks something like this.
let xhr = new XMLHttpRequest();
xhr.method = 'GET';
xhr.url = 'https://slowmo.glitch.me/5000';
xhr.open(method, url, true);
xhr.send();
// Abort the request at a later stage
abortButton.addEventListener('click', function () {
xhr.abort();
});fetch wasn’t abortable when it was initially introduced.
the initial GitHub issue for aborting a fetch request was opened initially in 2015.
There were also many attempts to solve this problem outside of the fetch spec
like cancelable-promises and other hacks.
But, we now finally have the generic AbortController and the AbortSignal APIs.
These APIs are provided by the DOM standard, not by the language itself.
What is an AbortController?
As described in the DOM spec documentation
Though promises do not have a built-in aborting mechanism, many APIs using them require abort semantics.
AbortControlleris meant to support these requirements by providing anabort()method that toggles the state of a correspondingAbortSignalobject. The API which wishes to support aborting can accept anAbortSignalobject, and use its state to determine how to proceed.
// Create a instance of the AbortController
const controller = new AbortController();
const signal = controller.signal;
// Listen for abort signal, callback executed on controller.abort()
signal.addEventListener('abort', () => {
console.log(signal.aborted); // true
});
// Abort at a later stage, this will notify the signal
controller.abort();How to abort fetch request using AbortController?
fetch accepts AbortSignal as part of the second argument.
const controller = new AbortController();
const signal = controller.signal;
// API responds after 5s
// Note the 'signal' in the second argument
fetch('https://slowmo.glitch.me/5000', { signal })
.then((r) => r.json())
.then((response) => console.log(response))
.catch((err) => {
if (err.name === 'AbortError') {
console.log('Fetch was aborted');
} else {
console.error('Oops!', err);
}
});
// Abort the request after 2s
// This will abort the fetch with 'AbortError'
setTimeout(() => {
controller.abort();
}, 2000);Aborting the fetch aborts both the request and response.
The request fails with the error new DOMException('Aborted', 'AbortError').
The same
AbortSignal(signalin the above example) can be used to abort multiplefetchrequests.
Demo
AbortControlleris not only for fetch. it’s a generic API to abort asynchronous tasks. Eg: You can use it to implement a cancelable promise.
Browser support and polyfill
Many older browsers don’t support the AbortController and the AbortSignal APIs.
You can use either of these polyfills to make it work.
That’s it for now. If you enjoyed reading this post, give me a follow @ganapativs 😬
References:
- https://developers.google.com/web/updates/2017/09/abortable-fetch
- https://github.com/whatwg/fetch/issues/27
Thanks:
