JavaScript Throttling

In the previous lesson, we learned how debouncing waits for activity to stop before running a function. Now letโ€™s look at throttling, which keeps a function running at a steady pace while activity is still going.

โฑ๏ธ What is Throttling?

Throttling limits how often a function can run. No matter how many times the function is triggered, it runs at most once every set time interval.

Some events fire constantly. A scroll handler can run dozens of times per second, and so can mousemove or window resize. Running expensive code on every single one of those events slows the page down. Throttling fixes this by letting the function run on a fixed schedule, such as once every 200 milliseconds, while ignoring the extra triggers in between.

The core idea

Throttling guarantees a maximum rate. The function runs regularly during activity, but never more often than the interval you set.

๐Ÿ” Throttle vs Debounce

Throttling and debouncing both limit how often a function runs, but they behave differently. Debouncing waits for a pause, while throttling runs on a steady beat.

Technique When it runs Good for
Debounce Once, AFTER activity stops Search box, form validation
Throttle At most once every X ms DURING activity Scroll, mousemove, resize

The difference matters. If you want the latest value once the user finishes typing, you debounce. If you want regular updates while the user keeps scrolling, you throttle.

๐Ÿ› ๏ธ Building a Throttle Function

A throttle function uses a flag to remember whether it is currently waiting. When the function runs, it sets the flag and starts a timer. While the flag is set, extra calls are ignored. When the timer finishes, the flag is cleared and the next call is allowed.

throttling.js
function throttle(callback, delay) {
let waiting = false;
return function (...args) {
if (waiting) return; // โŒ ignore calls while waiting
callback.apply(this, args); // โœ… run right away
waiting = true;
setTimeout(() => {
waiting = false; // ready for the next call
}, delay);
};
}

Letโ€™s walk through what each part does:

  • throttle(callback, delay) takes the function we want to limit and a delay in milliseconds, then returns a brand new function that wraps it.
  • let waiting = false is the flag that remembers whether we are inside a cooldown. It lives in the closure, so it keeps its value between calls.
  • if (waiting) return is the gate. While waiting is true, every call exits immediately and the callback never runs.
  • callback.apply(this, args) runs the original function right away, passing along the same this and arguments it was called with.
  • waiting = true flips the flag on so the next calls hit the gate above and get ignored.
  • The setTimeout starts the cooldown timer and sets waiting = false once delay passes, opening the gate for the next call.

This means the callback runs at the start of each interval, then blocks every call until the timer resets it.

Timestamp version

Another common approach stores the last run time and compares it to Date.now(). Both work. The flag with setTimeout is the easiest to read when you are getting started.

๐Ÿ“œ A Practical Scroll Handler

Here is throttling applied to a real scroll event. The handler runs at most once every 200 milliseconds, even though scrolling fires the event far more often.

throttling.js
function onScroll() {
console.log("Scroll position:", window.scrollY);
}
// โœ… run the handler at most once every 200ms
const throttledScroll = throttle(onScroll, 200);
window.addEventListener("scroll", throttledScroll);

Here is what each line is doing:

  • onScroll is the work we want to limit. It logs the current vertical scroll position from window.scrollY.
  • throttle(onScroll, 200) wraps onScroll so it can run at most once every 200 milliseconds, and we store the wrapped version in throttledScroll.
  • window.addEventListener("scroll", throttledScroll) attaches the throttled version, not the raw handler, so the browser calls the limited function on every scroll event.

Without throttling, onScroll might run a hundred times during a single swipe. With throttling, it runs about five times per second, which is smooth enough for things like showing a โ€œback to topโ€ button or updating a progress bar.

โš ๏ธ Common Mistakes to Avoid

Mistake Problem Solution
Confusing throttle with debounce The function runs at the wrong moment Throttle runs during activity, debounce runs after it stops
Picking the wrong technique A search box throttles instead of debounces Match the tool to the goal before coding
Interval too large The page feels laggy and unresponsive Lower the delay until updates feel smooth
Interval too small Almost nothing is throttled, performance suffers Raise the delay so fewer calls get through

๐Ÿ”ง Try It Yourself!

  1. Copy the throttle function into a script.
  2. Attach a throttled handler to the scroll event that logs window.scrollY.
  3. Scroll the page and watch how often the message appears in the console.
  4. Change the delay from 200 to 1000 and notice how the updates slow down.
  5. Replace scroll with mousemove and throttle it the same way.

๐Ÿงฉ What Youโ€™ve Learned

  • โœ… Throttling limits a function to at most once every set interval
  • โœ… It suits events that fire constantly, like scroll, mousemove, and resize
  • โœ… Throttle runs DURING activity; debounce runs AFTER activity stops
  • โœ… A flag with setTimeout is a simple way to build a throttle function
  • โœ… The right delay keeps the page both smooth and efficient

๐Ÿš€ Whatโ€™s Next?

Now that you can control how often code runs, letโ€™s put your skills together in a small project. Letโ€™s continue to Calculator.

Share & Connect