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.
AbortController
is meant to support these requirements by providing anabort()
method that toggles the state of a correspondingAbortSignal
object. The API which wishes to support aborting can accept anAbortSignal
object, 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
(signal
in the above example) can be used to abort multiplefetch
requests.
Demo
AbortController
is 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: