Go beyond the theory. Learn how to create cancellable events and network requests with hands-on examples.
The `AbortController` API splits the ability to cancel an operation from the operation itself. You create a controller, pass its "signal" to one or more asynchronous tasks (like event listeners or fetch requests), and then call the controller's `.abort()` method to cancel all of them at once.
You create this object.
You get this from the controller.
You pass the signal to it.
This example demonstrates the primary rule: `AbortController` is single-use. To re-enable listeners after an abort, you must create a new controller. Click "Activate" and move your mouse over the box, then "Deactivate" and try again.
Listeners are Inactive
Move mouse here
Waiting for actions...
let controller1;
function activateListeners() {
// Create a NEW controller each time
controller1 = new AbortController();
const signal = controller1.signal;
// Add listeners with the new signal
el.addEventListener('mouseenter', fn1, { signal });
el.addEventListener('mouseleave', fn2, { signal });
}
function deactivateListeners() {
// Abort the current controller
if (controller1) {
controller1.abort();
}
}
Here we use `AbortController` for its original purpose: cancelling a network request. Click "Fetch Data" to start a simulated 5-second download, and try cancelling it midway.
let controller2;
async function fetchData() {
controller2 = new AbortController();
const signal = controller2.signal;
try {
// Pass signal to fetch options
const res = await fetch(URL, { signal });
} catch (err) {
// Check if the error was an abort
if (err.name === 'AbortError') {
console.log('Fetch aborted!');
}
}
}
function cancelFetch() {
if (controller2) {
controller2.abort();
}
}
Click "Fetch Data" to begin.
Use AbortController when: cleaning up multiple listeners at once (e.g., in a component), using anonymous functions as listeners, or coordinating cancellation with a `fetch` request.
Use removeEventListener when: you only need to toggle a single, named event listener. It's slightly more direct for simple cases.
No. Once `.abort()` is called, the controller is permanently in an "aborted" state. It cannot be reset or reused.
Any task attached to its signal is cancelled forever. To re-add listeners or make another cancellable request, you **must create a new `AbortController` instance**.
It works perfectly out of the box. TypeScript includes all the necessary type definitions for `AbortController` and `AbortSignal`, so you get full type safety and autocompletion with no extra configuration.
const controller = new AbortController();
// controller is typed as AbortController
const signal = controller.signal;
// signal is typed as AbortSignal