DEV Community

Rich Polo
Rich Polo

Posted on

Debounce vs Throttle in JavaScript — Build Both From Scratch

Search boxes that fire a request on every keystroke and scroll handlers that run 100 times a second are classic performance bugs. Two tiny functions fix them.

Debounce: wait until the user stops

function debounce(fn, delay = 300) {
  let timer;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}
Enter fullscreen mode Exit fullscreen mode

Each call resets the timer. fn only runs once calls stop for delay ms.

Throttle: run at most once per interval

function throttle(fn, interval = 200) {
  let last = 0;
  let trailing;
  return function (...args) {
    const now = Date.now();
    const remaining = interval - (now - last);
    clearTimeout(trailing);
    if (remaining <= 0) {
      last = now;
      fn.apply(this, args);
    } else {
      // make sure the final call isn't lost
      trailing = setTimeout(() => {
        last = Date.now();
        fn.apply(this, args);
      }, remaining);
    }
  };
}
Enter fullscreen mode Exit fullscreen mode

Try it in a page

<input id="search" placeholder="Type...">
<p id="out"></p>
<p id="scroll"></p>
<div style="height:3000px"></div>
<script>
  /* paste debounce and throttle here */
  const out = document.getElementById("out");
  document.getElementById("search").addEventListener(
    "input",
    debounce(e => { out.textContent = "Searching for: " + e.target.value; }, 400)
  );
  const s = document.getElementById("scroll");
  window.addEventListener(
    "scroll",
    throttle(() => { s.textContent = "scrollY = " + Math.round(scrollY); }, 250)
  );
</script>
Enter fullscreen mode Exit fullscreen mode

Test it in Node

const log = debounce(x => console.log("debounced:", x), 100);
log(1); log(2); log(3);          // prints only "debounced: 3"

const tick = throttle(x => console.log("throttled:", x), 100);
let i = 0;
const id = setInterval(() => { tick(++i); if (i === 10) clearInterval(id); }, 30);
// prints roughly every 100ms, plus the final value
Enter fullscreen mode Exit fullscreen mode

Which one?

Situation Use
Search-as-you-type, autosave, window resize end debounce
Scroll position, mouse move, infinite scroll check throttle

Rule of thumb: debounce cares about the last event, throttle cares about a steady rhythm.

Top comments (0)