gotchajavascriptModerate
Debounce delays execution; throttle limits rate — they are not interchangeable
Viewed 0 times
debouncethrottlerate limitingevent handlingsetTimeoutclearTimeout
Problem
Debounce and throttle are often confused. Using debounce for a scroll handler means the callback never fires during continuous scrolling. Using throttle for a search input means the last keystroke may be ignored.
Solution
Debounce: fire only after a gap of silence. Reset the timer on every call. Use for search inputs — fire after user stops typing. Throttle: fire at most once per interval regardless of call rate. Use for scroll/resize — fire consistently during the event. Leading/trailing options control whether to fire at the start or end of the interval.
Why
Debounce collapses rapid calls into one delayed call. Throttle spreads calls evenly over time. The confusion comes from both 'reducing call frequency' but with opposite guarantees.
Gotchas
- A plain debounce with trailing=true never fires during continuous events — add leading=true if you need immediate feedback
- Throttle with trailing=true fires an extra call at the end — can cause double-fire at low event rates
- requestAnimationFrame is a browser-native 60fps throttle for visual updates — prefer it over manual throttle for animations
Code Snippets
Debounce and throttle implementations
function debounce(fn, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
function throttle(fn, interval) {
let last = 0;
return function(...args) {
const now = Date.now();
if (now - last >= interval) {
last = now;
fn.apply(this, args);
}
};
}
// Usage
const onSearch = debounce(fetchResults, 300); // fire 300ms after last keystroke
const onScroll = throttle(updateUI, 16); // fire at most every 16ms (~60fps)Context
Optimizing event handlers for scroll, resize, input, or any high-frequency DOM events
Revisions (0)
No revisions yet.