Cancelling async tasks with AbortController

AbortController is a built-in DOM class used to cancel fetches, but it can be used in other ways too

· 3 min read · Last updated:
A stop sign on a street

I learned the other day that AbortController can be used to not only abort fetches, but can be used in basically any way you like. Just like promises can be used to represent any future, pending value, AbortController can be used as a controller to stop pending async operations. This was exciting to me, which I realize probably comes off sad sounding and means that I need more excitement in my life but–whatever–that’s besides the point.

The typical usage of AbortController that I was aware of was using it with fetch like this:

let abortController = new AbortController();
fetch('/url', { signal: abortController.signal });
// NOTE that an abortController's signal can associated with multiple fetches too
abortController.abort();

Calling the abort method cancels the HTTP request and rejects the promise. How exactly an AbortController.signal is consumed wasn’t clear to me but it turns out it’s pretty simple.

AbortControllerSignals implement the DOM’s EventTarget interface, or in other words, are an event emitter with an addEventListener method. This allows us to use it like this:

let abortController = new AbortController();
abortController.signal.addEventListener('abort', (event) => {
  // implement your canceling logic here
})

So let’s write a function that does an async task that allows the caller to pass an AbortControllerSignal to it to cancel it. I’ve occasionally had reason to create a function that basically promisifies setTimeout in actual code, so we’ll use that as our example: