Suggest an editImprove this articleRefine the answer for “AbortController in JavaScript”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`AbortController` is a built-in object that creates a "cancellation signal" (`AbortSignal`) and lets you interrupt, with a single `abort()` call, any asynchronous operation that listens to that signal.** The controller holds the "cancelled or not" state, while `AbortSignal` is the flag the asynchronous code watches: it exposes the `signal.aborted` property and an `abort` event. You pass the signal into `fetch(url, { signal })`, and after `controller.abort()` the request is torn down immediately with an `AbortError`. ```javascript const controller = new AbortController(); fetch('https://example.com/data', { signal: controller.signal }); controller.abort(); // the request is aborted ``` **Key point:** a controller is single use, after `abort()` its signal stays `aborted === true` forever, so create a new `AbortController` for every new operation.Shown above the full answer for quick recall.Answer (EN)Image**`AbortController` is a special object that lets you create a "cancellation signal" (`AbortSignal`) and send a "cancel" command to asynchronous operations that listen to it.** Put simply: `AbortController` manages the "cancelled or not" state, while `AbortSignal` is the flag that asynchronous code can watch. ## Theory ### TL;DR - `new AbortController()` creates a controller with two key members: `signal` and `abort()`. - `controller.signal` is an `AbortSignal` object that you pass into an asynchronous operation. - `controller.abort()` flips the signal into the cancelled state and fires all of its listeners. - In `fetch`, an aborted request rejects with an error whose `err.name === 'AbortError'`. - The signal can also be supported in your own asynchronous functions: read `signal.aborted` and listen for the `abort` event. - A controller is single use: the next operation needs a new instance. ### Quick example ```javascript const controller = new AbortController(); // create the controller const signal = controller.signal; // take the signal out of it fetch('https://example.com/data', { signal }) .then(response => response.json()) .then(data => console.log(data)) .catch(err => { if (err.name === 'AbortError') { console.log('The request was aborted'); } else { console.error('Error:', err); } }); // Abort the request after 1 second: setTimeout(() => { controller.abort(); // cancellation }, 1000); ``` What happens: 1. We create the controller, then pass `controller.signal` into `fetch`. 2. When we call `controller.abort()`, `fetch` is interrupted instantly and throws an `AbortError`. ### How it works under the hood `AbortController` creates an object with two key properties: - `signal`, an `AbortSignal` object that can be passed into an asynchronous operation; - `abort()`, a method that activates that signal: it changes the signal's state and calls every registered handler. The controller itself cannot cancel anything. It only flips a flag, and the actual interruption is done by whichever API you handed the signal to. ### What AbortSignal can do `AbortSignal`: - has an `.aborted` property (a boolean: `true` if the operation was cancelled); - can listen for the `"abort"` event. ```javascript const controller = new AbortController(); const signal = controller.signal; signal.addEventListener('abort', () => { console.log('The operation was cancelled!'); }); controller.abort(); // => "The operation was cancelled!" ``` ### Where you can use it `AbortController` is supported by many APIs: | API | Supports cancellation? | | --- | --- | | `fetch()` | Yes | | `ReadableStream`, `WritableStream` | Yes | | `WebSocket` (through your own wrapper) | Partially | | `setTimeout` / `setInterval` (through the AbortSignal API in Node 20+ or a browser polyfill) | Yes | | `navigator.sendBeacon()` (in some browsers) | Partially | | Your own async functions | Yes, if you implement the support by hand | ### Example with a Promise and custom cancellation You can use the signal inside your own asynchronous functions: ```javascript function wait(ms, signal) { return new Promise((resolve, reject) => { const timeout = setTimeout(resolve, ms); signal.addEventListener('abort', () => { clearTimeout(timeout); reject(new Error('Cancelled by the user')); }); }); } const controller = new AbortController(); wait(5000, controller.signal) .then(() => console.log('5 seconds have passed')) .catch(err => console.log(err.message)); setTimeout(() => controller.abort(), 2000); // cancel after 2 seconds ``` Result: ```text Cancelled by the user ``` ### Reuse and the API summary A controller is single use: - after `controller.abort()` its `signal` gets `.aborted = true` forever; - to cancel again you have to create a **new** `AbortController`. | Property or method | What it does | | --- | --- | | `new AbortController()` | creates a controller | | `.signal` | the signal to pass into an async API | | `.abort()` | sends the "cancel" command | | `signal.aborted` | `true` if cancelled | | `signal.addEventListener('abort', fn)` | listens for the cancellation event | ### Common mistakes - **Reusing one controller for several requests.** After the first `abort()` the signal is already cancelled, so the next `fetch` using it fails immediately. Create a new controller per request. - **Swallowing `AbortError` like an ordinary failure.** In `catch` you must check `err.name === 'AbortError'` separately, otherwise the user sees a failure message where the request was cancelled on purpose. - **Expecting `abort()` to cancel the work on the server.** Only the client side is cancelled: the browser tears down the connection, but the server may have already performed the operation. - **Forgetting to remove the `abort` listener.** In your own functions the listener should be removed once the work finishes (for example with `{ once: true }`), otherwise a long lived signal keeps a reference alive and leaks memory. - **Ignoring an already aborted signal.** If you write your own async function, check `signal.aborted` at the start, because the signal may have been aborted before the function was even called.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.