diff --git a/src/signal.ts b/src/signal.ts index 84efe42..9ab9259 100644 --- a/src/signal.ts +++ b/src/signal.ts @@ -1,4 +1,3 @@ - /** * Ensures that a passed {@link Function} is called when the given {@link AbortSignal} is aborted. * @@ -11,3 +10,38 @@ export function handleAbortSignalAbort(signal: AbortSignal | undefined, fn: () = signal?.addEventListener('abort', fn); } } + +/** + * Returns a {@link Promise} for the abort of the passed {@link AbortSignal}. This may be + * immediately. + */ +export function promiseForSignal( + signal: AbortSignal, + resolveWith: Promise | T = Promise.reject(new Error('aborted')), +): Promise { + if (signal.aborted) { + return Promise.resolve(resolveWith); + } else { + return new Promise((resolve) => { + signal.addEventListener('abort', () => resolve(resolveWith)); + }); + } +} + +/** + * Returns a new {@link AbortSignal} that can be individually aborted, but which is also tied to + * the lifetime of the passed signal. + * + * If the passed signal is already aborted, returns it directly. + */ +export function derivedSignal(previous?: AbortSignal) { + if (previous?.aborted) { + return { signal: previous, abort: () => {} }; + } + + const c = new AbortController(); + const abort = () => c.abort(); + + previous?.addEventListener('abort', abort); + return { signal: c.signal, abort }; +} diff --git a/tsconfig.json b/tsconfig.json index 0a9ba84..beb6670 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,9 +5,9 @@ // if you'd like to warn if you're using modern features, change these // both to e.g., "es2017" - "module": "esnext", - "target": "esnext", - "moduleResolution": "nodenext", + "module": "NodeNext", + "target": "ESNext", + "moduleResolution": "NodeNext", "esModuleInterop": true, "allowSyntheticDefaultImports": true,