Debouncing with setTimeout & clearTimeout
Wait for a pause in typing
Lesson 16 of 20 · 12 min · Module 5: Smoother interactions
Searching on every keystroke wastes work: typing “javascript” starts ten searches, and with a server behind the box, ten requests. Debouncing waits until people pause, then runs the work once.
Start this lesson →Free. No installation: you write and run the code in your browser, and it is checked automatically.
By the end, you’ll be able to…
- Schedule and cancel work with setTimeout and clearTimeout
- Write a reusable debounce function
- Avoid wasted work while people type
The idea
setTimeout(fn, ms) schedules a function and returns an id, and clearTimeout(id) cancels it. A debounced function cancels the previous timer on every call and starts a new one, so the work only runs after a whole delay without calls. Wrapping the idea in a reusable debounce(fn, delay) function keeps it in one place.
const timer = setTimeout(() => console.log('Saved'), 1000);
clearTimeout(timer); // cancelled: nothing is logged
01A timer you can cancel
setTimeout returns a number that identifies the timer. Passing it to clearTimeout cancels the call if it has not happened yet. Clearing a timer that already ran, or undefined, simply does nothing, which keeps debounce short.
const id = setTimeout(() => console.log('later'), 500);
clearTimeout(id);
console.log('cancelled');cancelled02A closure keeps the timer
debounce returns a new function. The timer variable lives in debounce’s scope, so every call of the returned function sees the timer of the previous call and can cancel it.
function debounce(fn, delay) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
}
03Choose the delay for people
Between about 200 and 400 ms feels instant, yet skips the keystrokes in between. Debouncing also suits saving drafts and validating as people type. Its cousin, throttling, runs at most once per interval instead of waiting for a pause, which suits scrolling.
Your turn
debounce(fn, delay). It returns a new function that, every time it is called, cancels the timer of the previous call and starts a new one, so fn runs once, with the latest arguments, delay ms after the last call. Then make the input listener call search() through a 300 ms debounce instead of on every keystroke.What the checks look for
- Every lesson shows at the start
- Typing does not search straight away
- The search runs about 300 ms after typing stops
- Fast typing searches once, with the latest text
- Clearing the box shows every lesson again
Take this with you
Cancel the previous timer, start a new one: the work runs once, after the pause.
Go a little further
Show “Searching…” in the status as soon as people type, and replace it with the count when the search runs.