timefence
v0.1.1
Published
Put a time limit on any promise, with real AbortSignal cancellation and a composable deadline signal. Zero dependencies.
Downloads
249
Maintainers
Readme
timefence
Put a time limit on any promise — with real
AbortSignalcancellation and a composable deadline signal. Zero dependencies.
Promise.race([op, timer]) "times out" — but the slow operation keeps running in
the background, holding a socket open and burning quota. timefence gives the
operation an AbortSignal that fires on timeout, so the underlying fetch (or any
cooperative work) is actually cancelled, not just ignored.
import { withTimeout } from "timefence";
// On timeout, the fetch is aborted — not left dangling.
const res = await withTimeout((signal) => fetch(url, { signal }), 5000);Why timefence?
- Real cancellation. The function form receives an
AbortSignalthat fires on timeout or when your ownsignalaborts — wire it tofetch/streams. - Fallback or throw. Reject with a typed
TimeoutError, or resolve with afallbackvalue when you'd rather degrade than fail. - Composable deadlines.
deadline(ms, signal?)returns anAbortSignalthat trips afterms(or earlier if your signal aborts) — likeAbortSignal.timeoutbut composable, with anunref'd timer so it won't keep Node alive. - Zero dependencies, ESM + CJS + types.
Install
npm install timefence
# or: pnpm add timefence / yarn add timefence / bun add timefenceAPI
withTimeout(input, ms, options?) → Promise<T>
input is a promise, or (signal) => Promise (preferred — enables cancellation).
await withTimeout(slowPromise, 1000); // throws TimeoutError
await withTimeout((s) => fetch(url, { signal: s }), 1000); // aborts the fetch
await withTimeout(loadFresh(), 800, { fallback: () => cached });| Option | Type | Default | Description |
| ---------- | ----------------------- | ------- | ---------------------------------------------------- |
| message | string | — | Message for the thrown TimeoutError. |
| signal | AbortSignal | — | Cancel early from outside (rejects with its reason). |
| fallback | () => T \| Promise<T> | — | Resolve with this on timeout instead of throwing. |
ms = Infinity disables the timeout while still honoring signal.
deadline(ms, signal?) → AbortSignal
const signal = deadline(10_000, userSignal);
await fetch(url, { signal }); // aborts after 10s, or when userSignal doesTimeoutError / isTimeoutError(err)
try {
await withTimeout(op, 1000);
} catch (err) {
if (isTimeoutError(err)) retryOrDegrade();
else throw err;
}Pairs well with
retryfn— retry an operation that timed out.runpool/ratebucket— bound concurrency and rate;timefencebounds time.
Contributors ✨
This project follows the all-contributors specification. Contributions of any kind are welcome — code, docs, bug reports, ideas, reviews! See the emoji key for how each contribution is recognized, and open a PR or issue to get involved.
Thanks goes to these wonderful people:
License
MIT © Tung Tran
