From 073a6fab3f0f7e9bca16e916468c933c012bdcf4 Mon Sep 17 00:00:00 2001 From: Richie Bendall Date: Fri, 5 Sep 2025 18:24:30 +1200 Subject: [PATCH] Support automatic disposal --- index.js | 8 +++++++- readme.md | 19 +++++++++++++++++++ test.js | 16 ++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 45ef936..7a919b2 100644 --- a/index.js +++ b/index.js @@ -12,5 +12,11 @@ export default function timeoutSignal(timeout) { // Allow Node.js processes to exit early if only the timeout is running timeoutId?.unref?.(); - return controller.signal; + const {signal} = controller; + + signal[Symbol.dispose] = () => { + clearTimeout(timeoutId); + } + + return signal; } diff --git a/readme.md b/readme.md index 83f1e73..3f07b02 100644 --- a/readme.md +++ b/readme.md @@ -25,6 +25,25 @@ try { } ``` +With [`using`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/using#browser_compatibility) syntax for automatic disposal: + +```js +import timeoutSignal from 'timeout-signal'; + +async function hello() { + using signal = timeoutSignal(5000); + + try { + const response = await fetch('https://www.google.com', {signal}); + // Handle response + } catch (error) { + if (signal.aborted) { + // Handle abortion + } + } +} +``` + ## API ### timeoutSignal(timeout) diff --git a/test.js b/test.js index bf63d76..9347950 100644 --- a/test.js +++ b/test.js @@ -1,4 +1,5 @@ import test from 'ava'; +import {setTimeout as delay} from 'node:timers/promises'; import {pEvent} from 'p-event'; import timeSpan from 'time-span'; import timeoutSignal from './index.js'; @@ -16,3 +17,18 @@ test('main', async t => { t.true(signal.aborted); t.true(end() < 500); }); + +test('using', async t => { + let isAborted = false; + + { + using signal = timeoutSignal(300); + signal.addEventListener('abort', () => { + isAborted = true; + }) + await delay(100); + } + + await delay(500); + t.false(isAborted); +})