UNPKG

timeout-flow

Version:

Fluent, composable, pauseable JavaScript timers and time control flows — plus RAF utilities for frame-based logic.

75 lines (66 loc) 2.08 kB
// ./src/abort.js /** * Standardized AbortError factory. * Works in browsers and Node runtimes that may not have DOMException. * * We resolve the best implementation once at module load time. * This avoids feature detection in the hot path. */ let createAbortError; // Prefer native DOMException when available (browser + modern Node). if (typeof DOMException !== 'undefined') { createAbortError = (message = 'Aborted') => new DOMException(message, 'AbortError'); } else { // Fallback for runtimes without DOMException. createAbortError = (message = 'Aborted') => { const err = new Error(message); err.name = 'AbortError'; return err; }; } export { createAbortError }; /** * Attach an AbortSignal listener and return a cleanup function. * - If `signal` is missing, returns a no-op cleanup. * - If already aborted, calls `onAbort()` immediately and returns a no-op cleanup. * * @param {AbortSignal | null | undefined} signal * @param {() => void} onAbort * @returns {() => void} cleanup */ export function attachAbort(signal, onAbort) { if (!signal) return () => { }; if (signal.aborted) { onAbort(); return () => { }; } signal.addEventListener('abort', onAbort, { once: true }); return () => signal.removeEventListener('abort', onAbort); } /** * Manage AbortSignal listener lifecycle for "pending work" cases. * Call `add()` when work becomes pending and `remove()` when it’s resolved/canceled. * * @param {AbortSignal | null | undefined} signal * @param {() => void} onAbort * @returns {{ add: () => void, remove: () => void, reset: () => void }} */ export function pendingAbort(signal, onAbort) { let cleanup = null; return { add() { if (cleanup) return; cleanup = attachAbort(signal, onAbort); }, remove() { if (!cleanup) return; cleanup(); cleanup = null; }, reset() { if (cleanup) cleanup(); cleanup = null; }, }; }