Text-input processing
Run a search or validation only after the user pauses typing.
JS Puzzles · Const
debounce(f, ms) returns a wrapper that waits until calls stop for ms milliseconds, then invokes f once with the latest arguments. New calls cancel the previous scheduled invocation.
Calling debounce returns a wrapper. Each wrapper call cancels the previous timer and starts a new one, so the original function runs only after ms milliseconds without another call, using the latest arguments and preserving the caller's this value.
debounce(f, ms)| Name | Type | Description |
|---|---|---|
f | Function | The function whose calls are delayed and coalesced. |
ms | number | The inactivity interval in milliseconds. |
A wrapper function that delays invocation of f.
function debounce(func, ms) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), ms);
};
}
const save = debounce(value => console.log(value), 100);
save("a");
save("b");
setTimeout(() => save("c"), 150);The first two calls are superseded; after the final call in each burst, the wrapped function runs once.
Run a search or validation only after the user pauses typing.
Handle the final pointer position after movement stops.
Coalesce a burst of events when intermediate states do not need processing.
A debounced wrapper postpones the original call until the specified quiet period has elapsed. Every new wrapper call cancels the previous timeout, and only the final call's arguments reach the original function.
Follow-up: How would you preserve the receiver? Use a normal function wrapper and invoke the target with func.apply(this, args), rather than using an arrow wrapper that captures the wrong this.
The timeout is reset after every invocation of the wrapper. Therefore, a continuous stream of calls keeps postponing execution; the wrapped function runs once only after the stream stops for ms milliseconds.
Follow-up: What happens if calls never stop? The trailing invocation may never occur, because the required inactivity interval is never reached.
Debounce suits event sequences such as key presses or mouse movement when only the final state should be processed. Throttle is different: it runs no more often than the specified interval and is useful for regular updates.
Follow-up: Which should handle continuous scrolling updates? Usually throttle, when periodic updates are needed; debounce is better when processing the eventual final result.
throttlecall/applyDecorators and forwarding