CodeBlanks Logo Icon CodeBlanks

Debounce and throttle

Learn debounce and throttle patterns.

Debounce and throttle

Debounce and throttle are two patterns that limit how often a function is called. Debounce runs once after a quiet period following the last call. Throttle runs at most once per interval.

Debounce example: instead of calling an API on every keystroke in a search box, you call once 300 ms after the user stops typing. function debounce(fn, delay) { let timer = null; return function(...args) { if (timer) clearTimeout(timer); timer = setTimeout(() => { fn.apply(null, args); timer = null; }, delay); }; }. If you make three calls in a row, only the last one runs, delay ms after it. clearTimeout cancels the previous timer; so only the last call survives. This reduces unnecessary work.

Delaying with setTimeout

The core of debounce is setTimeout. The call setTimeout(() => { fn.apply(null, args); }, delay) invokes the function after delay milliseconds. On each new call the previous timer is cancelled with clearTimeout(timer) and a new one is set.

The result: the function runs once, delay ms after the last call. With fn.apply(null, args) the original arguments are preserved. The timer = null assignment clears the timer reference after the job is done. This pattern is used in search boxes, window resize and scroll, which fire frequently. Throttle works differently: it runs the first call immediately, then ignores further calls for delay. Debounce waits, throttle limits.

Practice Write the debounce function

Write function debounce(fn, delay) with let timer = null;. Return function(...args) { if (timer) clearTimeout(timer); timer = setTimeout(() => { fn.apply(null, args); timer = null; }, delay); }. main is ready: fn is called three times, after 100 ms console.log("Pending: " + calls).

Starter code

index.js
// Write a debounce(fn, delay) function
// Run once, delay ms after the last call
// write here

Sample solution

index.js
function debounce(fn, delay) {
  let timer = null;
  return function(...args) {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(null, args);
      timer = null;
    }, delay);
  };
}

let calls = 0;
const fn = debounce(function() {
  calls++;
  console.log("Called: " + calls);
}, 50);

fn();
fn();
fn();
setTimeout(() => {
  console.log("Pending: " + calls);
}, 100);

Expected output

Çağrıldı: 1
Bekleyen: 1

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Complete the clearTimeout call

Question
if (timer) ____(timer);
Answer
if (timer) clearTimeout(timer);

Explanation: clearTimeout cancels the previous timer.

2 Match each piece to its role

Term Meaning
setTimeout Schedules a delayed call
clearTimeout Cancels the previous timer
debounce Once after the last call
throttle At most once per interval

3 What happens after three debounce calls in a row?

index.js
const fn = debounce(f, 50); fn(); fn(); fn();
  • It runs three times
  • It never runs
  • It runs once, 50 ms after the last call Correct answer
  • It runs three times immediately

Explanation: Debounce runs once, delay ms after the last call.

All lessons in Intermediate