Abort and timeouts
| AbortController | |
| Abort after ms | |
| Cancel without fetch | |
| Clean timers |
AbortController
AbortController ships as a global since Node 15, so no import is needed. Create one controller per task and pass its signal down. Calling abort tells every listener that the work is no longer wanted.
const ctrl = new AbortController();
ctrl.signal.addEventListener("abort", () => {
console.log("aborted");
});
ctrl.abort();
Abort after ms
Pair the controller with a timer to bound the wait. Start the timer next to the work and call abort when it fires. The worker sees the abort event and can stop early.
const ctrl2 = new AbortController();
const timer = setTimeout(() => {
ctrl2.abort();
}, 1000);
ctrl2.signal.addEventListener("abort", () => {
console.log("timed out");
});
Cancel without fetch
Node 16 has no global fetch, but https requests accept the same signal. Pass the signal in the request options. Destroy the request on abort so sockets do not linger.
import * as https from "https";
const ctrl3 = new AbortController();
const req = https.get("https://example.com", { signal: ctrl3.signal });
ctrl3.signal.addEventListener("abort", () => {
req.destroy();
});
Clean timers
Always clear the timeout once the work settles. A live timer keeps the process awake and fires a late abort by surprise. Put clearTimeout in a finally block so both success and failure clean up.
async function guarded(work: Promise<string>): Promise<string> {
const ctrl = new AbortController();
const timer = setTimeout(() => ctrl.abort(), 1000);
try {
return await work;
} finally {
clearTimeout(timer);
}
}
Next: Async error handling
Article author: Arthur Isaev