AbortController
AbortController is a built-in object that produces a reusable signal you hand to async work, so calling its abort() method can cancel a fetch, timer, or any operation listening to that signal.
Learn AbortController in our free JavaScript course — an interactive lesson with runnable examples, a practice exercise and a quick reference.
Part of the free JavaScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
It is how you stop work you no longer need: cancelling a stale search request, tearing down a fetch when a component unmounts, or enforcing a hard timeout.
What You'll Learn in This Lesson
📚 Prerequisites: You should know promises and async/await with try/catch, since aborting surfaces as a rejected promise.
🔔 Real-World Analogy: An AbortController is a fire alarm . The controller is the pull handle; the signal is the wiring that runs to every room. You give the signal to each async task ("listen for the alarm"). Pulling the handle ( abort() ) rings everywhere at once and every task that was listening stops what it is doing.
1️⃣ The Controller and Its Signal
Create a controller with new AbortController() . It exposes a read-only signal that you pass to the operation you want to be able to cancel, and an abort() method that flips that signal to the aborted state. The signal has an aborted boolean and fires an "abort" event when triggered.
2️⃣ Cancelling Async Work & Catching AbortError
Pass signal to fetch and call abort() to cancel the request. The fetch promise rejects with an AbortError , which you catch and distinguish from a real network failure by checking err.name . This is the classic "cancel the previous search as the user types" pattern:
⚠️ Always check err.name : Treating an AbortError as a real error shows users scary "request failed" messages for something they (or your code) caused on purpose.
The runnable demo below uses a cancellable delay that listens to the signal — exactly the shape fetch follows — so you can watch an abort reject with an AbortError in Node:
🎯 Your Turn #1 — Trip the Signal
Replace the blank with the method that cancels the controller so the event fires.
3️⃣ AbortSignal.timeout — Deadlines for Free
When you only need a deadline, skip the controller entirely. AbortSignal.timeout(ms) returns a signal that auto-aborts after ms milliseconds. There is also AbortSignal.any([...]) to abort as soon as any of several signals fires — handy for "cancel on either a timeout or the user clicking stop".
🎯 Your Turn #2 — Identify the Cancellation
Replace the blank so the code checks for a deliberate abort instead of treating it as a real error.
🧠 Quick Recall
Predict the output before revealing the answer.
true — abort() permanently flips the signal's aborted flag.
No — the signal stays aborted. Create a fresh new AbortController() for each new operation.
Common Errors & Fixes
- 1️⃣ Passing the controller instead of its signal
- 2️⃣ Treating an abort as a real failure
- 3️⃣ Reusing one controller for every request
- 4️⃣ Forgetting to remove abort listeners
🎯 Mini Challenge — Cancel the Loser
Start two waits. When the fast one finishes, abort the slow one so its cleanup runs. This mirrors cancelling a stale request once fresher data arrives.
Quick Reference — AbortController
Goal
Code
Create
const c = new AbortController();
Pass to fetch
fetch(url, { signal: c.signal })
Cancel
c.abort();
Detect
e.name === "AbortError"
Auto deadline
AbortSignal.timeout(3000)
📚 Keep Learning
- • MDN — AbortController
- • MDN — AbortSignal (timeout, any)
- • MDN — fetch() with a signal
Frequently Asked Questions
🎉 Lesson Complete — AbortController!
- ✅ A controller owns a one-shot signal you hand to async work
- ✅ abort() cancels everything listening; fetch rejects with an AbortError
- ✅ Check err.name === "AbortError" to ignore deliberate cancellations
- ✅ AbortSignal.timeout(ms) gives you a deadline with no controller
Up next: Web Workers — run heavy work off the main thread. 🧵
Practice quiz
What two things does a new AbortController() give you?
- A signal and an abort() method
- A promise and a resolve() method
- Two separate signals
- A signal and a timeout
Answer: A signal and an abort() method. A controller exposes a read-only signal you hand to async work, plus an abort() method that trips that signal.
After controller.abort(), what is controller.signal.aborted?
- false
- true
- undefined
- It throws
Answer: true. abort() permanently flips the signal's aborted flag to true.
When you abort a fetch, the fetch promise rejects with what?
- A plain Error
- A DOMException whose name is 'AbortError'
- null
- A TypeError
Answer: A DOMException whose name is 'AbortError'. An aborted fetch rejects with a DOMException whose name is 'AbortError'.
How do you tell a deliberate cancellation apart from a real network failure?
- Check err.message
- Check err.code
- Check err.name === 'AbortError'
- You cannot tell them apart
Answer: Check err.name === 'AbortError'. Checking err.name === 'AbortError' distinguishes an intentional abort from a genuine error.
Can you reuse an AbortController after calling abort()?
- Yes, it resets automatically
- No — the signal stays aborted forever
- Only if you call reset()
- Only for fetch, not timers
Answer: No — the signal stays aborted forever. A signal is one-shot; once aborted it stays aborted, so you create a fresh controller per operation.
What does AbortSignal.timeout(ms) return?
- A controller
- A promise
- A signal that auto-aborts after ms milliseconds
- A number
Answer: A signal that auto-aborts after ms milliseconds. AbortSignal.timeout(ms) returns a signal that aborts itself after the given delay, with no controller needed.
Which value do you pass to fetch's options?
- signal: controller
- signal: controller.signal
- controller: signal
- abort: controller
Answer: signal: controller.signal. You pass the signal, not the controller: fetch(url, { signal: controller.signal }).
When a signal created by AbortSignal.timeout fires, signal.reason is a DOMException named what?
- AbortError
- TimeoutError
- RangeError
- DeadlineError
Answer: TimeoutError. A timeout signal aborts with a DOMException whose name is 'TimeoutError'.
What event does a signal fire when it is aborted?
- 'cancel'
- 'stop'
- 'abort'
- 'error'
Answer: 'abort'. The signal fires an 'abort' event, which any listener attached to that signal reacts to.
What combines several signals so an operation aborts when ANY of them fires?
AbortSignal.any([...]) aborts as soon as any of the supplied signals fires.
Continue this course
- Previous: Async Iterators & for-await-of
- Next: Web Workers