Explain debouncing and throttling, and when you would use each.
Both limit how often a function runs, but they answer different questions.
Debounce — wait until the activity stops, then run once. Every new call resets the timer.
function debounce(fn, delay) {
let t;
return (...args) => {
clearTimeout(t);
t = setTimeout(() => fn(...args), delay);
};
}Throttle — run at most once per interval, no matter how many calls arrive.
function throttle(fn, limit) {
let waiting = false;
return (...args) => {
if (waiting) return;
fn(...args);
waiting = true;
setTimeout(() => { waiting = false; }, limit);
};
}Which to use:
- Debounce when only the final state matters — a search-as-you-type box, validating a field after the user stops typing, saving a draft.
- Throttle when you need regular updates during the activity — scroll position, mouse move, an infinite-scroll trigger, window resize.
Note: Debouncing a scroll handler is a classic mistake: nothing happens at all until the user stops scrolling.





