UNPKG

timeout-flow

Version:

Fluent, composable, pauseable JavaScript timers and time control flows — plus RAF utilities for frame-based logic.

95 lines (68 loc) 3.73 kB
## 🛯 Frame-Based Timing (RAF Utilities) These 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. --- ### 👉 API Summary | 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 | --- ### ✨ Key Advantages - 🔄 **Frame-sync**: Triggered in sync with visual updates (60Hz or higher) - 🛌 **Background-tab safe**: No CPU use when inactive - **Energy efficient**: Great for battery-conscious apps - 🧘 **Smoother UX**: Especially under load or heavy visuals --- ### 🛠 Example Usage ```js import { debounceRaf } from './raf/debounceRaf.js'; // Wait 1 frame after rapid calls const onMouseMove = debounceRaf(() => { drawPreview(); }); // Wait 250ms of inactivity (with frame-based throttle) const onResize = debounceRaf('250ms', () => { updateLayout(); }); ``` ```js import { afterRaf } from './raf/afterRaf.js'; afterRaf('2s', () => { showIntroAnimation(); }); ``` ```js import { everyRaf } from './raf/everyRaf.js'; const loop = everyRaf('1s', () => { console.log('heartbeat'); }); ``` ```js import { throttleRaf } from './raf/throttleRaf.js'; // Throttle a scroll event to at most once per animation frame const onScroll = throttleRaf((e) => { handleScroll(e); }); // Throttle to once every 3 frames (skip 2 frames) const onDrag = throttleRaf(drawFrame, 2); ``` ```js import { waitForRaf } from './raf/waitForRaf.js'; // Wait for an element to become visible or stable await waitForRaf(() => document.querySelector('#panel')?.offsetHeight > 0); ``` --- ### 📦 File Locations | 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 |