UNPKG

@jcoreio/abortable

Version:

memory-leak-proof function to wrap a promise to reject when a signal is aborted

40 lines (36 loc) 1.35 kB
export const newAbortError = () => new DOMException('This operation was aborted', 'AbortError') const noop = () => {} export function abortable<T>( promise: Promise<T>, signal: AbortSignal | undefined ): Promise<T> { if (!signal) return promise return new Promise<T>((resolve, reject) => { const cleanup = () => { const callbacks = { resolve, reject } // Prevent memory leaks. If the input promise never resolves, then the handlers // below would retain this enclosing Promise's resolve and reject callbacks, // which would retain the enclosing Promise and anything waiting on it. // By replacing references to these callbacks, we enable the enclosing Promise to // be garbage collected resolve = noop reject = noop // Memory could also leak if the signal never aborts, unless we remove the abort // handler signal.removeEventListener('abort', onAbort) return callbacks } const onAbort = () => cleanup().reject(signal.reason) promise.then( (value) => cleanup().resolve(value), (error: unknown) => cleanup().reject(error) ) if (signal.aborted) { // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors reject(signal.reason) } else { signal.addEventListener('abort', onAbort) } }) }