
Security News
curl Shuts Down Bug Bounty Program After Flood of AI Slop Reports
A surge of AI-generated vulnerability reports has pushed open source maintainers to rethink bug bounties and tighten security disclosure processes.
timeout-flow
Advanced tools
Fluent, composable, pauseable JavaScript timers and time control flows — plus RAF utilities for frame-based logic.
Fluent, human-readable time control for JavaScript.
TimeoutFlow makes working with time-based logic intuitive — think of it as a modern, composable upgrade to setTimeout and setInterval, with added powers like chaining, conditional logic, pause/resume, retries, and more.
TimeoutFlow is not just a wrapper for setTimeout.
It's a composable mini-framework for expressing time as fluent logic.
We believe temporal behavior in JavaScript should be:
if, while, label, and jumpTo() — not just repetition.TimeoutFlow gives you atomic time primitives (after, every, debounce, retry)
and a fluent builder (flow()) to script rich behavior over time — like a timeline you can control.
Think of TimeoutFlow as setTimeout() with superpowers. But more importantly, think of it as a way to write time like you write logic.
flow()
.after('1s', () => console.log('Start'))
.every('500ms', (i) => console.log(`Tick ${i}`), 3)
.after('1s', () => console.log('Done'))
.start();
This isn’t about wrapping timers. It’s about orchestrating intent — clearly, fluently, and with full control.
npm install timeout-flow
after("1s", fn) — delay execution (via AfterTimer)
every("500ms", fn, count?) — repeat execution with optional limit (via EveryTimer)
flow() — create fluent, chainable timelines with:
.after(), .every(), .loop(n).if(), .unless(), .label(), .jumpTo().while(), .doWhile()Utilities: debounce(), throttle(), retry(), waitFor()
// 1. Delayed Execution
import { after } from 'timeout-flow';
after('2s', () => console.log('Waited 2 seconds...'));
// 2. Repeating with Pause & Resume
import { every, after as wait } from 'timeout-flow';
const ticker = every('1s', i => console.log(`Tick ${i}`), 5);
wait('2.5s', () => ticker.pause());
wait('4s', () => ticker.resume());
// 3. Debounced Input
import { debounce } from 'timeout-flow';
const search = debounce('300ms', (e) => {
console.log('Searching for:', e.target.value);
});
document.querySelector('input').addEventListener('input', search);
// 4. Retry a Failing Request
import { retry } from 'timeout-flow';
await retry(() => fetch('/api/data'), {
attempts: 4,
delay: '1s',
backoff: true
});
// 5. Wait for DOM Change
import { waitFor } from 'timeout-flow';
await waitFor(() => document.querySelector('#loaded'), {
interval: '250ms',
timeout: '5s'
});
console.log('Element loaded!');
// 6. Fluent Timeline
import { flow } from 'timeout-flow';
flow()
.after('1s', () => console.log('Step 1'))
.every('500ms', (i) => console.log(`Tick ${i}`), 3)
.after('1s', () => console.log('Final Step'))
.start();
// 7. Conditional & Labeled Logic
let debug = true;
flow()
.after('1s', () => console.log('Boot sequence'))
.if(() => debug)
.after('500ms', () => console.log('Debug logs enabled'))
.label('loop')
.every('1s', i => console.log(`Frame ${i}`), 3)
.after('500ms', () => console.log('Restarting...'))
.jumpTo('loop')
.start();
// 8. Controlled Loop
let energy = 3;
flow()
.doWhile(() => energy-- > 0)
.every('400ms', () => console.log(`Blast (${energy})`))
.after('1s', () => console.log('Energy depleted'))
.start();
import { debounce, throttle, retry, waitFor } from 'timeout-flow';
debounce('300ms', fn) — Run only after silencethrottle('1s', fn) — Run at most once per time windowretry(fn, { attempts, delay, backoff }) — Resilient retry for async callswaitFor(() => condition, { timeout, interval }) — Await condition changeThese helpers use requestAnimationFrame under the hood to provide smooth, energy-efficient timing. Ideal for visual UI flows, canvas apps, scroll/resize behavior, and performance-sensitive interactions.
All raf utilities automatically pause in background tabs, unlike timers.
| Function | Purpose | Best For |
|---|---|---|
afterRaf() | Runs a function once after N ms, using requestAnimationFrame. | Idle effects, UI post-load, paint batching |
everyRaf() | Repeats a function every N ms, throttled via frames. | Sanity loops, smooth polling, visual checks |
debounceRaf() | Debounces a function using frames instead of timeouts. | Drag/move handlers, visual updates |
debounceRaf('300ms', fn) | Debounces like traditional debounce, but frame-aware. | Resize events, paused background flows |
throttleRaf() | Throttles execution to at most once per frame. | Scroll events, pointermove, paint-heavy flows |
throttleRaf(fn, 2) | Throttles to once every 3 frames (frameSkip = 2). | Advanced visuals, slower sync without timers |
waitForRaf() | Waits for a condition to become true using a frame-based loop. | DOM readiness, layout stability, visibility checks |
import { debounceRaf } from 'timeout-flow';
const onMouseMove = debounceRaf(() => {
drawPreview();
});
const onResize = debounceRaf('250ms', () => {
updateLayout();
});
import { afterRaf } from 'timeout-flow';
afterRaf('2s', () => {
showIntroAnimation();
});
import { everyRaf } from 'timeout-flow';
const loop = everyRaf('1s', () => {
console.log('heartbeat');
});
import { throttleRaf } from 'timeout-flow';
const onScroll = throttleRaf((e) => {
handleScroll(e);
});
const onDrag = throttleRaf(drawFrame, 2);
import { waitForRaf } from 'timeout-flow';
await waitForRaf(() => document.querySelector('#panel')?.offsetHeight > 0);
| File | Description |
|---|---|
raf/afterRaf.js | One-time timer with frame pause support |
raf/everyRaf.js | Interval timer using requestAnimationFrame |
raf/debounceRaf.js | Smart debounce with optional duration and frame pause |
raf/throttleRaf.js | Input-event throttle using frame-skip control |
raf/waitForRaf.js | Waits for truthy condition using passive frame polling |
--{DR.WATT v3.0}--
FAQs
Fluent, composable, pauseable JavaScript timers and time control flows — plus RAF utilities for frame-based logic.
We found that timeout-flow demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
A surge of AI-generated vulnerability reports has pushed open source maintainers to rethink bug bounties and tighten security disclosure processes.

Product
Scan results now load faster and remain consistent over time, with stable URLs and on-demand rescans for fresh security data.

Product
Socket's new Alert Details page is designed to surface more context, with a clearer layout, reachability dependency chains, and structured review.