How to Cancel a Fetch Request

JavaScript promises have always been a major win for the language -- they've led to a revolution of asynchronous coding that has vastly improved performance on the web. One shortcoming of native promises is that there's no true way to cancel a fetch ...until now. A new AbortController has been added to the JavaScript specification that will allow developers to use a signal to abort one or multiple fetch calls.

Here's the flow of how canceling a fetch call works:

Create an AbortController instance

instance That instance has a signal property

property Pass the signal as a fetch option for signal

as a fetch option for Call the AbortController 's abort property to cancel all fetches that use that signal.

Aborting a Fetch

The following is the bare bones of canceling a fetch request:

const controller = new AbortController(); const { signal } = controller; fetch("http://localhost:8000", { signal }).then(response => { console.log(`Request 1 is complete!`); }).catch(e => { console.warn(`Fetch 1 error: ${e.message}`); }); // Abort request controller.abort();

An AbortError occurs upon the abort call, so you can listen for aborted fetches in the catch by comparing the error name:

}).catch(e => { if(e.name === "AbortError") { // We know it's been canceled! } });

Passing the same signal to multiple fetch calls will cancel all requests with that signal:

const controller = new AbortController(); const { signal } = controller; fetch("http://localhost:8000", { signal }).then(response => { console.log(`Request 1 is complete!`); }).catch(e => { console.warn(`Fetch 1 error: ${e.message}`); }); fetch("http://localhost:8000", { signal }).then(response => { console.log(`Request 2 is complete!`); }).catch(e => { console.warn(`Fetch 2 error: ${e.message}`); }); // Wait 2 seconds to abort both requests setTimeout(() => controller.abort(), 2000);

In his article Abortable fetch, Jake Archibald details a nice utility for creating abortable fetches without the need for all of the boilerplate:

function abortableFetch(request, opts) { const controller = new AbortController(); const signal = controller.signal; return { abort: () => controller.abort(), ready: fetch(request, { ...opts, signal }) }; }