Debounce With Trailing Edge Invocation

A debounce utility that collapses rapid calls into one trailing invocation with flush and cancel support for deterministic tests.

JavascriptCli Tooling

Code

export function debounce(fn, waitMs, scheduler = setTimeout) {
  if (typeof fn !== "function") throw new TypeError("fn must be a function");
  if (!Number.isFinite(waitMs) || waitMs <= 0) throw new RangeError("waitMs must be a positive number");
  let timer = null;
  let lastArgs = null;
  const wrapped = (...args) => {
    lastArgs = args;
    if (timer !== null) clearTimeout(timer);
    timer = scheduler(() => {
      timer = null;
      const a = lastArgs;
      lastArgs = null;
      fn(...a);
    }, waitMs);
  };
  wrapped.flush = () => {
    if (timer !== null) {
      clearTimeout(timer);
      timer = null;
    }
    if (lastArgs !== null) {
      const a = lastArgs;
      lastArgs = null;
      fn(...a);
    }
  };
  wrapped.cancel = () => {
    if (timer !== null) {
      clearTimeout(timer);
      timer = null;
    }
    lastArgs = null;
  };
  return wrapped;
}