temporal-fn
v0.1.1
Published
Intent-based function execution
Readme
temporal-fn
Intent-based function execution for JavaScript.
Most timing utilities (debounce, throttle) expose mechanics. temporal-fn exposes intent.
Instead of asking “how often should this run?”, you declare “what behavior do I want over time?”
Why debounce is not enough
Debounce and throttle are useful, but they often blur important behavioral differences:
- Did the user pause? (Wait for silence)
- Did the user persist long enough? (Verify commitment)
- Must the action eventually happen? (Guarantee execution)
These are different intentions, but they are usually handled with ad-hoc timing hacks. temporal-fn makes those intentions explicit.
Mental model
Think in terms of time semantics, not timers.
- Events ──▶ Intention ──▶ Execution
You choose how time should matter.
API
stable(fn, { window })
Executes once, only after calls stop for window milliseconds.
import { stable } from "temporal-fn";
const onResize = stable(
() => {
console.log("layout settled");
},
{ window: 300 }
);Use when: You care about silence (e.g., waiting for a user to stop typing or resizing).
intentional(fn, { min })
Executes only if the caller persists for at least min milliseconds.
import { intentional } from "temporal-fn";
const onDrag = intentional(
() => {
console.log("user really meant this");
},
{ min: 500 }
);Use when: You care about commitment (e.g., preventing accidental clicks or short-lived hover states).
impatient(fn, { max })
Executes no later than max milliseconds, even if calls keep happening.
import { impatient } from "temporal-fn";
const onScroll = impatient(
() => {
console.log("must run eventually");
},
{ max: 1000 }
);Use when: Execution must be guaranteed (e.g., ensuring a UI update happens during a long, continuous scroll).
Control API
All returned functions support manual overrides:
wrapped.cancel(): Abort execution.wrapped.flush(): Force execution immediately.
Design Principles
| Feature | Description | | ----------------- | ----------------------------------- | | Singular | Executes at most once per cycle. | | Pure | No global state or DOM assumptions. | | Lightweight | Tiny footprint (~1.7 kB). | | Deterministic | Highly testable behavior. |
Non-goals
- Not a reactive framework.
- Not a heavy-duty scheduler.
- Not a replacement for complex async queues.
This library does one thing: model intent over time — clearly.
