JavaScript Interview Question: Implement debounce
Task: write debounce(fn, wait) that returns a function which only calls fn after it stops being called for wait milliseconds. Typical use: search-as-you-type.
Solution
function debounce(fn, wait) {
let timer;
return function (...args) {
clearTimeout(timer); // cancel the previous pending call
timer = setTimeout(() => fn.apply(this, args), wait);
};
}
const onSearch = debounce((q) => fetchResults(q), 300);
input.addEventListener('input', (e) => onSearch(e.target.value));
Points to mention
- The closure keeps
timerbetween calls. - A regular
function(not an arrow) for the returned wrapper, sothisis whatever the caller used;applypasses it on with the latest arguments. - Only the last call's arguments are used.
Follow-up: add cancel and flush
function debounce(fn, wait) {
let timer, lastArgs, lastThis;
function debounced(...args) {
lastArgs = args;
lastThis = this;
clearTimeout(timer);
timer = setTimeout(() => { timer = undefined; fn.apply(lastThis, lastArgs); }, wait);
}
debounced.cancel = () => { clearTimeout(timer); timer = undefined; };
debounced.flush = () => {
if (timer === undefined) return;
debounced.cancel();
fn.apply(lastThis, lastArgs);
};
return debounced;
}
Follow-up: debounce vs throttle
Debounce waits for a pause and runs once at the end (search input, autosave). Throttle runs at most once per interval during continuous activity (scroll, resize, mousemove).
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.