Skip to content

Instantly share code, notes, and snippets.

@Jamesernator
Last active November 4, 2020 21:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jamesernator/c04b2518617a8da6deb123e2dedc07be to your computer and use it in GitHub Desktop.
Save Jamesernator/c04b2518617a8da6deb123e2dedc07be to your computer and use it in GitHub Desktop.
doAbortable
export default async function doAbortable<R>(
signal: AbortSignal | undefined,
func: (abortSignal: AbortSignal) => R | Promise<R>,
): Promise<R> {
const controller = new AbortController();
const abortInner = () => controller.abort();
if (signal?.aborted) {
abortInner();
} else {
signal?.addEventListener("abort", abortInner, { once: true });
}
try {
return await func(controller.signal);
} finally {
// remove listener from the original signal, this allows our local controller
// to be collected as there are no longer any references to it, by consequence
// this allows the inner signal to be collectable as long as no references remain
signal?.removeEventListener("abort", abortInner);
}
}
import doAbortable from "./doAbortable.ts";
import AbortError from "./AbortError.ts";
export default function delay(time: number, abortSignal?: AbortSignal): Promise<void> {
return doAbortable(abortSignal, abortSignal => {
return new Promise((resolve, reject) => {
if (abortSignal.aborted) { reject(new AbortError()) }
const timeout = setTimeout(resolve, time);
abortSignal.addEventListener('abort', () => {
clearTimeout(timeout);
reject(new AbortError());
}, { once: true });
});
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment