mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
48 lines
1.3 KiB
TypeScript
48 lines
1.3 KiB
TypeScript
/**
|
|
* Compose multiple abort signals into one that aborts when **any** input fires.
|
|
* Uses native `AbortSignal.any` when available, otherwise falls back to a
|
|
* manual `AbortController` composition for Chromium ≤115 and similar runtimes.
|
|
*/
|
|
export function anyAbortSignal(signals: AbortSignal[]): AbortSignal {
|
|
if ('any' in AbortSignal) {
|
|
return AbortSignal.any(signals);
|
|
}
|
|
|
|
const controller = new AbortController();
|
|
|
|
for (const signal of signals) {
|
|
if (signal.aborted) {
|
|
controller.abort(signal.reason);
|
|
return controller.signal;
|
|
}
|
|
|
|
signal.addEventListener('abort', () => controller.abort(signal.reason), {
|
|
signal: controller.signal,
|
|
});
|
|
}
|
|
|
|
return controller.signal;
|
|
}
|
|
|
|
/**
|
|
* Race a promise against an abort signal. Rejects immediately if the signal
|
|
* is already aborted or becomes aborted before the promise settles.
|
|
*/
|
|
export function abortable<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {
|
|
if (signal.aborted) {
|
|
return Promise.reject(signal.reason);
|
|
}
|
|
|
|
let onAbort: () => void;
|
|
|
|
return Promise.race([
|
|
promise,
|
|
new Promise<never>((_, reject) => {
|
|
onAbort = () => reject(signal.reason);
|
|
signal.addEventListener('abort', onAbort, { once: true });
|
|
}),
|
|
]).finally(() => {
|
|
signal.removeEventListener('abort', onAbort);
|
|
});
|
|
}
|