What is the difference between debouncing and throttling?
Both limit how often a function runs when it is called repeatedly, but they limit it in different ways.
Debouncing waits for the calls to stop. Each new call cancels the pending one and starts the clock again, and the function runs once, after the last call, with the arguments from that last call. The classic example is a search box that only queries the server once the user has stopped typing.
Throttling caps the rate. The function runs immediately on the first call, and then further calls within the window are dropped until the window expires. The classic example is a scroll handler that has to do work on every scroll event but may only do it a few times a second.
// Debounce: run only after the calls stop.
const debounce = (fn, waitMs) => {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), waitMs);
};
};
// Throttle: run at most once per interval.
const throttle = (fn, waitMs) => {
let blocked = false;
return (...args) => {
if (blocked) return;
blocked = true;
fn(...args);
setTimeout(() => { blocked = false; }, waitMs);
};
};That difference shows up in the timing. The debounced function does not run at all until the calls stop, so it never runs mid-burst. The throttled function runs at the start of the burst and then stays quiet for the rest of the window.
There is also a trailing variant of throttle, which runs the function once more at the end of the window with the most recent arguments, and that is often what you actually want for something like a scroll handler, where you want the final position to be handled as well.