AbortController helpers — auto-abort timeout, signal composition, Promise integration.
Module abort | Source packages/front/fw/src/io/sync/abort.js | Deps none | Worker-safe yes
Facilitates usage of native AbortController/AbortSignal without reimplementing the standard. For higher-level cancellation patterns (cleanup hooks, task pools), see cancellable.
Resolve
const abort = runtime.resolve('abort');
// Returns: { timeout, any, wait, race, throwIfAborted, error }
API
| Method | Signature | Returns |
|---|---|---|
timeout |
(ms: number) => { signal, controller, abort } |
Object with signal auto-aborted after ms |
any |
(...signals: AbortSignal[]) => AbortSignal |
Combined signal (aborts on the first) |
wait |
(signal: AbortSignal) => Promise<never> |
Promise that rejects when the signal aborts |
race |
(promise, signal?) => Promise |
Short-circuits promise if signal aborts |
throwIfAborted |
(signal?) => void |
Throws if signal already aborted |
error |
(reason?: string) => DOMException |
Creates a standard AbortError |
abort.timeout(ms)
Creates an AbortController that auto-aborts after ms ms. The timer is cleaned up if abort() is called manually.
ms <= 0or non-numeric → throws.- The returned
abort(reason?)function also cancels the timer (no leak).
abort.any(...signals)
Polyfill of AbortSignal.any(signals) — delegates to the native if available (Chrome 116+, Firefox 124+).
- Signal already aborted at call time → returns an already-aborted signal.
- 0 arguments or non-
AbortSignalargument → throws.
abort.wait(signal)
Returns a Promise<never> that rejects as soon as signal aborts. Listener is automatically cleaned up.
abort.race(promise, signal)
Short-circuits promise with an AbortError rejection if signal aborts first.
Important: does not cancel the underlying promise — the call site must also pass
signalto the consuming API (e.g.fetch(url, { signal })).
signal undefined/null → promise returned as-is (practical no-op for optional parameter).
abort.throwIfAborted(signal)
No-op if signal is undefined/null or not aborted. Throws signal.reason otherwise.
abort.error(reason?)
Creates a DOMException { name: 'AbortError' }. Falls back to a plain object if DOMException is unavailable.
Examples
Timeout on a fetch
const abort = runtime.resolve('abort');
async function fetchWithTimeout(url) {
const { signal } = abort.timeout(5000);
const data = await abort.race(fetch(url, { signal }), signal);
return data.json();
}
Signal composition (external cancellation + timeout)
const userSignal = userController.signal;
const { signal: timedSignal } = abort.timeout(10_000);
const combined = abort.any(userSignal, timedSignal);
await fetch(url, { signal: combined });
Wait for cancellation (gate pattern)
async function worker(signal) {
const workPromise = doLongWork();
await abort.race(workPromise, signal);
// If signal aborts, the following line does not execute
uploadResult();
}
Worker Usage
AbortController is available in Web Workers. Example: cancelling a cross-thread fetch.
const worker = fw.createWorker(
function ({ libs, args }) {
const { signal } = libs.abort.timeout(args.timeoutMs);
return fetch(args.url, { signal }).then(r => r.json());
},
{ dependencies: ['abort'], args: { url: '/api/data', timeoutMs: 3000 } }
);
Notes
race(promise, signal)does not cancel the underlying promise — passsignalto the API for true cancellation.- Native
AbortSignal.anyis preferred (Chrome 116+, Firefox 124+); otherwise lightweight polyfill. - No reimplementation of
AbortController— everything relies on the native standard. - For cleanup orchestration (LIFO hooks, pools) →
cancellable.
See also
- cancellable — cancellable tasks with cleanup hooks
- mutex — intra-context synchronization