- From: Jake Archibald <notifications@github.com>
- Date: Fri, 05 Feb 2021 02:45:56 -0800
- To: whatwg/dom <dom@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/dom/issues/946/773954201@github.com>
Sketching a pattern that doesn't rely on GC:
```js
function abortableSetTimeout(ms, { signal } = {}) {
return abortableTask(signal, (setOnAbort) => new Promise((resolve) => {
const timerId = setTimeout(() => resolve(), ms);
setOnAbort(() => clearTimeout(timerId));
}));
}
```
Where this is the implementation of `abortableTask`:
```js
/**
* @param {AbortSignal | undefined} signal
* @param {(setAbort: () => void) => void | undefined} taskCallback
*/
async function abortableTask(signal, taskCallback) {
if (signal?.aborted) throw new DOMException("AbortError", "AbortError");
let onAbort, listener;
const setOnAbort = (callback) => (onAbort = callback);
const promise = taskCallback(setOnAbort);
return Promise.race([
new Promise((_, reject) => {
listener = () => {
onAbort?.();
reject(new DOMException("AbortError", "AbortError"));
};
signal?.addEventListener("abort", listener);
}),
promise,
]).finally(() => signal?.removeEventListener("abort", listener));
}
```
Some benefits of this:
- The task doesn't run at all if the signal has already aborted.
- `setOnAbort` can be called multiple times, which handles cases where the way to abort changes during different phases of the task.
- Works with primitives (`timerId` doesn't need to be an object)
I don't think it leaks, but I'd like a second opinion on that 😄.
Here's the DB example:
```js
class DB {
// wraps a database with AbortSignal API support
query(string, { signal } = {}) {
return abortableTask(signal, async (setOnAbort) => {
await this.open();
const query = this.createQuery(string);
setOnAbort(() => query.cancel());
return query.promise();
})
}
// rest of the implementation
}
```
--
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-773954201
Received on Friday, 5 February 2021 10:46:09 UTC