Chain multiple signals into one controller: if any of the signals aborts, the controller will be aborted. This is particularly useful since most APIs only accept a single AbortSignal input (fetch()
, axios, the AWS SDK, etc).
Works with browsers, NodeJS (16+), and spec-compliant polyfills.
At a minimum, you must pass one or more AbortSignals. However, the controller is optional: if a controller is not passed in, one will be created and returned.
import { chainAbortController } from "abortcontroller-chain";
// use your own controller
chainAbortController(controller, signal1, signal2, signal3);
// auto-create the controller
const controller = chainAbortController(signal1, signal2, signal3);
Say you're passing an AbortSignal into a long-running piece of code so you can end early if needed:
async function pollSomething(signal: AbortSignal) {
while (!signal.aborted) {
// keep polling until the signal says stop
}
}
But wait! You want to make an HTTP request with a deadline of 10 seconds:
const TEN_SECONDS = 10 * 1000; // ms
async function pollSomething(signal: AbortSignal) {
while (!signal.aborted) {
// abort after 500ms
const abortController = new AbortController();
setTimeout(() => abortController.abort(), TEN_SECONDS);
// do the fetch...
const result = await fetch("/something-something", {
// wait, this doesn't take into account the signal
// passed to pollSomething()
signal: abortController.signal,
});
/* ... */
}
}
Wouldn't it be great if the fetch-specific abortController
could be aborted by the outer signal? That's easy with the abortcontroller-chain
package:
import { chainAbortController } from "abortcontroller-chain";
const TEN_SECONDS = 10 * 1000; // ms
async function pollSomething(signal: AbortSignal) {
while (!signal.aborted) {
const abortController = new AbortController();
chainAbortController(abortController, signal);
setTimeout(() => abortController.abort(), TEN_SECONDS);
// do the fetch...
const result = await fetch("/something-something", {
// hooray! both signals are now respected
signal: abortController.signal,
});
/* ... */
}
}
You can further simplify the creation:
const abortController = chainAbortController(signal);
setTimeout(() => abortController.abort(), TEN_SECONDS);