DEV Community

DHANRAJ S
DHANRAJ S

Posted on

Debouncing and Throttling in JavaScript — Explained Simply

Hey!

Let me ask you something.

You have a search input. Every time the user types a letter — you send an API request to search.

User types "react" — that is 5 letters. That is 5 API calls. In under a second.

Now imagine 1000 users doing the same thing. Your server gets hammered with thousands of unnecessary requests. All for results the user never even waited to see.

That is a real problem. And debouncing is one of the ways to fix it.

But there is another situation too.

User scrolls a page. You want to run some code on every scroll event. The scroll event fires hundreds of times per second. Your code runs hundreds of times per second. Your app slows down noticeably.

That is a different problem. And throttling is the fix for that one.

Same goal — control how often something runs. Different approach. Let us understand both.


1. What Is Debouncing?

Debouncing means — wait until the user stops doing something, then run the function once.

Think of it like an elevator.

The elevator doors start to close. Someone puts their hand in. Doors open again. Timer resets. They wait. Another person runs in. Timer resets again.

The elevator only moves when nobody interrupts for a full few seconds.

That is debouncing. The function only fires after a pause in activity.


2. The Problem Without Debouncing

const input = document.getElementById("search");

input.addEventListener("input", () => {
  console.log("API call for:", input.value);
});
Enter fullscreen mode Exit fullscreen mode

User types "react" quickly.

API call for: r
API call for: re
API call for: rea
API call for: reac
API call for: react
Enter fullscreen mode Exit fullscreen mode

Five API calls. For one word. Most of them useless.

The user only cared about the result for "react" — not "r", "re", "rea", or "reac".


3. Debouncing — The Fix

function debounce(func, delay) {
  let timer;

  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => {
      func(...args);
    }, delay);
  };
}
Enter fullscreen mode Exit fullscreen mode

Let us understand this step by step.

timer — stores the setTimeout reference.

Every time the function is called — clearTimeout(timer) cancels the previous timer. A new timer starts.

If the function is called again before the timer finishes — the timer resets. Again. And again.

Only when the user stops for the full delay duration — the timer completes and the function runs. Once.


4. Using Debounce on the Search Input

function searchAPI(value) {
  console.log("API call for:", value);
}

const debouncedSearch = debounce(searchAPI, 500);

const input = document.getElementById("search");

input.addEventListener("input", () => {
  debouncedSearch(input.value);
});
Enter fullscreen mode Exit fullscreen mode

Now when the user types "react" quickly:

typing r   → timer starts
typing e   → timer resets
typing a   → timer resets
typing c   → timer resets
typing t   → timer resets
...500ms pause...
API call for: react   ← fires once
Enter fullscreen mode Exit fullscreen mode

One API call. For the complete word. That is debouncing.

Quick question for you.

What happens if the user types very slowly — one letter every second — with a 500ms debounce?

Each letter has more than 500ms of pause after it. So the API fires after every single letter. Debounce does not batch them — it just waits for a pause. If the pause is long enough between each letter — each one triggers separately.


5. What Is Throttling?

Throttling means — run the function at most once every X milliseconds. No matter how many times it is triggered.

Think of it like a tap with a flow controller.

You can open the tap fully. But the controller limits how much water comes out per second. The flow is controlled. Steady. Not a flood.

That is throttling. Steady execution at a fixed rate — no matter how fast events are firing.


6. The Problem Without Throttling

window.addEventListener("scroll", () => {
  console.log("scroll fired");
});
Enter fullscreen mode Exit fullscreen mode

Scroll down for 2 seconds.

scroll fired
scroll fired
scroll fired
scroll fired
... (hundreds of times)
Enter fullscreen mode Exit fullscreen mode

The scroll event fires maybe 100 times per second. If your scroll handler is doing heavy work — calculating positions, animating elements, fetching data — your app starts to stutter.


7. Throttling — The Fix

function throttle(func, limit) {
  let lastCall = 0;

  return function(...args) {
    const now = Date.now();

    if (now - lastCall >= limit) {
      lastCall = now;
      func(...args);
    }
  };
}
Enter fullscreen mode Exit fullscreen mode

lastCall — stores the timestamp of the last time the function actually ran.

Every time the function is triggered — it checks how much time has passed since the last run.

If enough time has passed — it runs and updates lastCall.

If not enough time has passed — it skips. No run.


8. Using Throttle on the Scroll Event

function handleScroll() {
  console.log("scroll handled at:", Date.now());
}

const throttledScroll = throttle(handleScroll, 500);

window.addEventListener("scroll", throttledScroll);
Enter fullscreen mode Exit fullscreen mode

Now when you scroll continuously for 3 seconds:

scroll handled at: 1000ms
scroll handled at: 1500ms
scroll handled at: 2000ms
scroll handled at: 2500ms
scroll handled at: 3000ms
Enter fullscreen mode Exit fullscreen mode

Runs once every 500ms. Steady. Controlled. Your app stays smooth.

Quick question for you.

What is the difference between what debounce and throttle would do here?

Debounce would wait until you stop scrolling — then fire once. Throttle fires regularly while you are still scrolling — just at a controlled rate.

For scroll — throttle makes more sense. You want the handler to run during scrolling, just not hundreds of times per second.


9. Debounce vs Throttle — Side by Side

Debounce Throttle
When it runs After the user stops At regular intervals while active
Fires Once after a pause Once every X milliseconds
Best for Search input, resize handler Scroll, mouse move, button spam
Think of it as Wait for silence Steady drip

10. Where Are These Used in Real Life?

Debounce is used for:

  • Search inputs — wait until user stops typing, then search
  • Window resize — wait until user stops resizing, then recalculate layout
  • Form validation — wait until user stops typing, then validate

Throttle is used for:

  • Scroll events — run handler steadily while scrolling
  • Mouse move — track position without firing every pixel
  • Button clicks — prevent double submitting a form

Quick Summary — 3 Things to Remember

  1. Debounce — waits for the user to stop, then fires once. Good for search inputs and resize events.

  2. Throttle — fires at a fixed rate no matter how many events come in. Good for scroll and mouse move.

  3. Both control how often a function runs — debounce delays until quiet, throttle limits to once per interval.


These two are asked in almost every JavaScript interview. Not just because they are useful — but because understanding them shows you actually think about performance.

Try building the search input example. Open the console. Type fast. Watch only one API call fire. Then remove the debounce. Type fast again. Watch the difference.

That hands-on comparison will make it stick better than any explanation.

If you have a question — drop it in the comments below.


Thanks for reading. Keep building.

Top comments (0)