- From: James Browning <notifications@github.com>
- Date: Sat, 06 Feb 2021 16:51:39 -0800
- To: whatwg/dom <dom@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/dom/issues/946/774568115@github.com>
I've been doing a similar thing since Node got support for `AbortSignal`, basically a wrapper that calls a function with a linked abort signal that gets disconnected once the promise returned from the function resolves:
```ts
// doAbortable.ts
export default async function doAbortable<R>(
signal: AbortSignal | undefined,
func: (abortSignal: AbortSignal) => R | Promise<R>,
): Promise<R> {
const innerController = new AbortController();
const abortInner = () => innerController.abort();
if (signal?.aborted) {
throw new AbortError();
} else {
signal?.addEventListener("abort", abortInner, { once: true });
}
try {
return await func(controller.signal);
} finally {
// this allows innerController to be garbage collected
// and hence if nothing is holding a strong reference to the signal
// that too may be collected
signal?.removeEventListener("abort", abortInner);
}
}
```
```ts
export default function animationFrame(abortSignal) {
// the inner abortSignal can be garbage collected
// once the promise returned resolves as there'll be
// no references to it remaining once doAbortable
// calls removeEventListener("abort", abortInner);
return doAbortable(abortSignal, (abortSignal) => {
return new Promise((resolve, reject) => {
const frameRequest = requestAnimationFrame(time => resolve(time));
abortSignal.addEventListener("abort", () => cancelAnimationFrame(frameRequest));
});
});
}
```
I've found it works fairly cleanly, although the extra wrapper is slightly annoying. This might be able to improved if [function](https://github.com/tc39/proposal-decorators/blob/master/EXTENSIONS.md#function-decorators-and-annotations) and [parameter](https://github.com/tc39/proposal-decorators/blob/master/EXTENSIONS.md#parameter-decorators-and-annotations) become a thing cause then I could just annotate the abort param and decorate it e.g:
```js
@abortable
export default function delay(time, @abortable.signal abortSignal) {
// ... create delay promise
}
```
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/dom/issues/946#issuecomment-774568115
Received on Sunday, 7 February 2021 00:51:51 UTC