Cancel In-Flight Async Operations
AbortController
AbortController is the standard cancellation primitive. Pass its signal to fetch, fs, timers, your own functions.
What you'll learn
- Cancel a fetch with a timeout
- Pass AbortSignal to async APIs
- Author cancelation-aware code
JavaScript’s standard cancellation primitive — same in browsers and
Node. Create a controller, pass its signal around, call abort()
to cancel everything tied to it.
The Basics
const ctrl = new AbortController();
const promise = fetch("https://example.com", { signal: ctrl.signal });
// somewhere else:
ctrl.abort(); // promise rejects with AbortError A Timeout
Cancel a request after N ms:
const ctrl = new AbortController();
const timeout = setTimeout(() => ctrl.abort(), 5_000);
try {
const res = await fetch("https://slow.api", { signal: ctrl.signal });
return await res.json();
} catch (err) {
if (err.name === "AbortError") {
throw new Error("timed out");
}
throw err;
} finally {
clearTimeout(timeout);
} Shortcut: AbortSignal.timeout(ms) creates a signal that auto-aborts.
const res = await fetch(url, { signal: AbortSignal.timeout(5_000) }); Multiple Signals
Cancel when any of N signals fire:
const combined = AbortSignal.any([userCancel, timeoutSignal]);
await fetch(url, { signal: combined }); Pass-Through
Many Node APIs accept signals:
import { readFile } from "node:fs/promises";
import { setTimeout } from "node:timers/promises";
const ctrl = new AbortController();
await readFile("huge.txt", { signal: ctrl.signal });
await setTimeout(1000, undefined, { signal: ctrl.signal }); If ctrl.abort() fires while these are in flight, they reject.
Authoring Cancel-Aware Code
async function pollWith({ signal }) {
while (true) {
if (signal?.aborted) throw new Error("aborted");
await doOneStep();
await new Promise((r) => setTimeout(r, 1000));
}
} Always accept { signal } from callers — it’s the convention.
When to Use
- Request timeouts
- “User clicked cancel”
- Stop a sub-task because its parent is going away
Once you have a function or pipeline that holds resources or runs indefinitely, an abort signal is the right API.
End of Chapter
That wraps the async core. Next chapter: HTTP — Node’s most popular use case.
HTTP Intro →