Kulpost BlogNotes and write-ups

← All posts

Debounce and Throttle

2026-10-30 · Kuligaposten

Some browser events fire far more often than you need them to. scroll, resize, and keyup on a search box can all trigger dozens of times a second. Wiring a handler directly to one of these is a fast way to tank performance. Debounce and throttle are the two standard fixes.

A JavaScript function running

Debounce

Debounce waits for a pause in activity before running. Every new call resets the timer, so the function only fires once things go quiet — perfect for a search input where you only want to fetch after the user stops typing.

JavaScript
function debounce(fn, delay) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), delay);
  };
}

const search = debounce((query) => {
  console.log('searching for', query);
}, 300);

input.addEventListener('keyup', (e) => search(e.target.value));

Type "hello" quickly and search runs once, 300ms after the last keystroke — not five times.

Throttle

Throttle guarantees a function runs at most once every n milliseconds, no matter how often it's called. That's the right shape for a scroll handler, where you want regular updates but not on every single pixel.

JavaScript
function throttle(fn, limit) {
  let waiting = false;
  return (...args) => {
    if (waiting) return;
    fn(...args);
    waiting = true;
    setTimeout(() => {
      waiting = false;
    }, limit);
  };
}

const onScroll = throttle(() => {
  console.log('scroll position:', window.scrollY);
}, 200);

window.addEventListener('scroll', onScroll);

Which one do you want?

Use case Debounce Throttle
Search-as-you-type Yes
Window resize recalculation Yes
Infinite scroll position tracking Yes
Button click spam prevention Yes
Drag/mousemove updates Yes

The pattern to remember: debounce answers "has activity stopped?", throttle answers "has enough time passed since the last run?". Pick based on whether you care about the last event or a steady stream of them.

Comments 0

← All posts