- 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