Throttling caps how often a function runs — at most once per interval — no matter how fast it's called. This version adds the controls real code needs: leading/trailing edge options that decide when within each window the call fires, and cancel/flush methods to drop or force a pending call.
Implement throttle(fn, wait, options). By default it fires on both the leading edge (immediately) and the trailing edge (once more after wait, if there were calls during the window). leading: false skips the immediate call; trailing: false skips the final one. Expose .cancel() and .flush().
function throttle(fn, wait, options) {
// options: { leading = true, trailing = true }
// returns a throttled fn with .cancel() and .flush()
}
// Fires at most once per 100ms while scrolling — immediately, then trailing:
const onScroll = throttle(update, 100);
throttle(save, 1000, { leading: false }); // wait 1s, then fire (no immediate)
throttle(log, 1000, { trailing: false }); // fire immediately, ignore the rest
onScroll.cancel(); // drop a pending trailing call (e.g. on unmount)
leading: true (default), the first call in a window fires fn immediately.trailing: true (default), a final call fires after wait, using the latest arguments, if any calls arrived during the window.wait — between the edges, extra calls are collapsed.cancel() — clears any pending trailing call so it never fires.flush() — invokes a pending trailing call right now instead of waiting.Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.