Debounce a Function in JavaScript
Delay running a function until input stops arriving, using a timer that resets on each call.
Also known as: JS debounce, debounce input handler
intermediate
A debounce wrapper clears and restarts a timer on every call, so the wrapped function only runs once activity pauses for the chosen delay.
What it is
Debouncing coalesces bursts of events — keystrokes, resize events, scroll — into a single call after a quiet period. The classic implementation captures a timer id in a closure, clears it on each invocation, and sets a new timeout. The wrapped function runs only when wait milliseconds pass with no further calls.
Use the rest parameter and apply to forward arguments and this so the debounced function behaves like the original. This is ideal for search-as-you-type, where you want to wait until the user stops typing before hitting the API.
Worked example
function debounce(fn, wait) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => fn.apply(this, args), wait);
};
}
// Usage
const onSearch = debounce((q) => {
console.log("searching for", q);
}, 300);
onSearch("a");
onSearch("ab");
onSearch("abc"); // only this call runs, ~300ms after the last keypress
Failure mode — when it misleads
Debounce is not throttle: if calls never pause, a debounced function may never run, which is wrong for things like scroll progress where you want a guaranteed cadence — use throttle there. Also, defining the debounced function inside a React render body creates a new timer each render and breaks it; memoize it with useMemo/useCallback or useRef.
Related entries
Sources & further reading
- setTimeout (MDN) (article)