throttle-debounce

Lightweight throttle and debounce functions for rate-limiting JavaScript event handlers.

Library
npm
v5.0.2
1,044stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
42/100Fair
Development Activity0
Maintenance20
Community60
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
65/100Good
Architecture75
Code Quality68
Innovation70
Learning Curve45

throttle-debounce is a small, dependency-free JavaScript utility providing two rate-limiting primitives: throttle, which caps how often a callback can run over a series of calls, and debounce, which waits for a pause in calls before running the callback once. It began as an ES Modules/CommonJS port of the classic jquery-throttle-debounce plugin, with the jQuery dependency removed, and ships as ESM, CJS, and UMD builds so it drops into any module system or a plain <script> tag.

Both functions return a wrapper with leading/trailing-edge control (noLeading, noTrailing, atBegin) and an attached cancel() method (with an upcomingOnly option to cancel just the next pending call), making it a common choice for taming resize, scroll, and input handlers without pulling in a larger utility library.

What You Get

  • throttle(delay, callback, options) — rate-limits a callback to run at most once per delay ms, with leading/trailing-edge control via noLeading/noTrailing
  • debounce(delay, callback, options) — delays a callback until delay ms have passed since the last call, with an atBegin option to fire on the leading edge instead
  • A cancel() method attached to every throttled/debounced function, including an upcomingOnly mode that cancels only the next scheduled call
  • Prebuilt ESM, CommonJS, and UMD distributions so the package works with import, require, or a plain <script> tag via jsDelivr/unpkg
  • Zero runtime dependencies and a tiny footprint, suitable for both browser and Node.js environments

Common Use Cases

  • Throttling resize or scroll event handlers so expensive layout or measurement code doesn’t run on every event
  • Debouncing search-as-you-type input handlers so an API call or filter only fires once typing pauses
  • Rate-limiting analytics or logging calls triggered by frequent user interactions
  • Cancelling a pending debounced save or autosave call when a component unmounts or the user navigates away

Under The Hood

Architecture The package is deliberately flat: throttle.js holds the single core implementation — a closure that tracks lastExec and a timeoutID, and returns a wrapper function with a cancel method attached — while debounce.js is a thin adapter that simply calls throttle with debounceMode set from the atBegin option, reusing the same state machine for both behaviors. index.js just re-exports both. There are no layers, no dependency injection, and no internal abstractions beyond this one shared closure; changing the timing logic in throttle.js’s wrapper function is the single point that would affect both throttling and debouncing behavior.

Tech Stack The source is plain ES2015+ JavaScript with JSDoc annotations (no TypeScript). Babel (@babel/preset-env plus @babel/plugin-transform-runtime) transpiles per the project’s Browserslist config, and Rollup (rollup.config.js) builds the cjs/, esm/, and umd/ output bundles declared in package.json’s exports map. Tests run through Karma against real browsers (Chrome, Firefox, and BrowserStack-hosted browsers in CI) using the QUnit test framework. Linting is ESLint with eslint-config-nitpick plus eslint-config-prettier/eslint-plugin-prettier, enforced pre-commit via Husky and lint-staged, and releases are cut with np.

Code Quality test/index.js is a substantial suite (adapted from the original jquery-throttle-debounce QUnit tests) that exercises leading/trailing-edge combinations, cancellation, and timing edge cases by driving the throttled/debounced functions through repeated timed calls. GitHub Actions runs lint and the Karma test suite (with a headless-browser fallback when BrowserStack secrets aren’t available) on every push and PR. There is no TypeScript and no bundled .d.ts file, so type safety relies entirely on the JSDoc comments in throttle.js and debounce.js; error handling is minimal because the functions have no failure modes to guard against beyond normal argument passing.

API Design The public surface is exactly two named exports with a shared options-object shape (noLeading/noTrailing/debounceMode for throttle, atBegin for debounce), so switching between throttling and debouncing a given callback requires no boilerplate beyond swapping the function name. The attached cancel() method (with an upcomingOnly variant) is a convenient, low-ceremony way to stop pending executions without holding onto a separate timer reference, and the README documents every option with runnable examples.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search