diff --git a/src/index.ts b/src/index.ts index 55c81d8..71e8e20 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,34 +9,37 @@ export interface ClearableSignal extends AbortSignal { */ export function anySignal (signals: Array): ClearableSignal { const controller = new globalThis.AbortController() + const unsubscribe: Function[] = [] - function onAbort (): void { - controller.abort() + function onAbort (reason: Error): void { + controller.abort(reason) - for (const signal of signals) { - if (signal?.removeEventListener != null) { - signal.removeEventListener('abort', onAbort) - } - } + clear() } for (const signal of signals) { if (signal?.aborted === true) { - onAbort() + onAbort(signal.reason) break } if (signal?.addEventListener != null) { - signal.addEventListener('abort', onAbort) + const cb = (): void => { + onAbort(signal.reason) + } + unsubscribe.push(() => { + if (signal?.removeEventListener != null) { + signal.removeEventListener('abort', cb) + } + }) + signal.addEventListener('abort', cb) } } function clear (): void { - for (const signal of signals) { - if (signal?.removeEventListener != null) { - signal.removeEventListener('abort', onAbort) - } - } + unsubscribe.forEach(cb => { + cb() + }) } const signal = controller.signal as ClearableSignal diff --git a/test/index.spec.ts b/test/index.spec.ts index d5b0e4c..7f4636e 100644 --- a/test/index.spec.ts +++ b/test/index.spec.ts @@ -156,4 +156,23 @@ describe('any-signal', () => { setMaxListeners(Infinity, signal) }) + + it('should be abort with custom signal reason', async () => { + if (!isNode && !isElectronMain) { + return + } + + class TimeoutError extends Error {} + class CancelError extends Error {} + + const c1 = new AbortController() + const c2 = new AbortController() + + const signal = anySignal([c1.signal, c2.signal]) + + c1.abort(new TimeoutError('timeout')) + c2.abort(new CancelError('cancel')) + expect(signal.reason instanceof CancelError).to.equal(false) + expect(signal.reason instanceof TimeoutError).to.equal(true) + }) })