Watchstop
Runtimes

Timer

setTimeout clock for Node, Bun, and Deno — one API.

createTimerClock() is the single server-side / non-rAF clock. Node, Bun, and Deno all share performance.now + setTimeout / clearTimeout. There is no createNodeClock, createBunClock, or createDenoClock in v1.

Export

type TimerClockOptions = {
  intervalMs?: number
}

function createTimerClock(options?: TimerClockOptions): Clock

From @watchstop/core.

Options

OptionDefaultMeaning
intervalMs16Delay passed to setTimeout for each schedule

16 approximates a 60 Hz UI tick for headless use. Callers may choose 100, 1000, etc. for coarser updates.

If intervalMs is provided and is not a finite number > 0, createTimerClock throws (RangeError). The default 16 is always valid.

Behavior

MethodImplementation
now()performance.now()
schedule(cb)setTimeout(() => cb(), intervalMs) — return the timeout handle
cancel(handle)clearTimeout(handle) (idempotent wrapper)

Runtime coverage

RuntimeSupported via this factory
Node.jsYes
BunYes
DenoYes
BrowserYes (but prefer Browser for UI)

Usage

import { Stopwatch, createTimerClock } from '@watchstop/core'

const sw = new Stopwatch(createTimerClock())
const slow = new Stopwatch(createTimerClock({ intervalMs: 100 }))

sw.start()

Detection

detectClock() returns createBrowserClock() when typeof requestAnimationFrame === 'function', otherwise createTimerClock(). That makes new Stopwatch() work in Node/Bun/Deno without configuration.

Constraints

  • No node:timers / node:perf_hooks hard imports required if globals exist; prefer portable globals so the same ESM build runs in Bun/Deno/browser.
  • Do not schedule with setInterval inside the clock — Stopwatch owns the repeat loop via repeated schedule calls.

On this page