race-cancellation
Version:
Utilities for using Promise.race([task, cancellation]) for async/await code.
50 lines (48 loc) • 1.58 kB
text/typescript
import composeRaceCancel from "./composeRaceCancel.js";
import {
CancellableAsyncFn,
CancelReason,
DisposableCancelExecutorFn,
DisposeFn,
RaceCancelFn,
} from "./interfaces.js";
import newRaceCancel from "./newRaceCancel.js";
/**
* Run a {@link CancellableAsyncFn} function with a {@link RaceCancelFn} adapted from a {@link DisposableCancelExecutorFn} function.
*
* @param cancellableAsync - a {@link CancellableAsyncFn} function
* @param disposableCancelExecutor - a {@link DisposableCancelExecutorFn} function that will only be called once
* @param outerRaceCancel - an optional outer {@link RaceCancelFn} function that will be composed with the {@link RaceCancelFn} function before being passed to the {@link CancellableAsyncFn} function.
* @public
*/
export default async function withCancel<TResult>(
cancellableAsync: CancellableAsyncFn<TResult>,
disposableCancelExecutor: DisposableCancelExecutorFn,
outerRaceCancel?: RaceCancelFn
): Promise<TResult> {
let cancelled = false;
let cancelReason: CancelReason | undefined;
let dispose: DisposeFn | undefined;
const raceCancel = newRaceCancel(
() => cancelled,
(resolveCancel) => {
dispose = disposableCancelExecutor((reason) => {
cancelled = true;
cancelReason = reason;
resolveCancel();
});
},
() => cancelReason
);
let result: TResult;
try {
result = await cancellableAsync(
composeRaceCancel(raceCancel, outerRaceCancel)
);
} finally {
if (dispose !== undefined) {
dispose();
}
}
return result;
}