AbortController provides a way to cancel asynchronous work.

The mental model is:

AbortController
      │
      └── signal ──→ operation
                         │
controller.abort() ──────┘
                         ↓
                     cancelled

Basic usage

Create a controller:

const controller = new AbortController();

Give its signal to something that supports cancellation:

fetch("/api/users", {
  signal: controller.signal,
});

Cancel it later:

controller.abort();

The operation receives the abort signal and cancels itself.


Fetch

const controller = new AbortController();
 
try {
  const response = await fetch("/api/users", {
    signal: controller.signal,
  });
 
  const users = await response.json();
} catch (error) {
  if (error.name === "AbortError") {
    console.log("Fetch was cancelled");
  } else {
    throw error;
  }
}

Event listeners

addEventListener() also supports AbortSignal.

Instead of:

element.addEventListener("click", handler);
 
// Later:
element.removeEventListener("click", handler);

you can do:

const controller = new AbortController();
 
element.addEventListener("click", handler, {
  signal: controller.signal,
});

Then:

controller.abort();

removes the listener automatically.


One controller can manage multiple things

const controller = new AbortController();
 
element.addEventListener("click", handler, {
  signal: controller.signal,
});
 
fetch("/api/data", {
  signal: controller.signal,
});

One call:

controller.abort();

cancels everything using that signal.