JavaScript Throttling
Table of Contents + โ
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.
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 adelayin milliseconds, then returns a brand new function that wraps it.let waiting = falseis the flag that remembers whether we are inside a cooldown. It lives in the closure, so it keeps its value between calls.if (waiting) returnis the gate. Whilewaitingistrue, every call exits immediately and the callback never runs.callback.apply(this, args)runs the original function right away, passing along the samethisand arguments it was called with.waiting = trueflips the flag on so the next calls hit the gate above and get ignored.- The
setTimeoutstarts the cooldown timer and setswaiting = falseoncedelaypasses, 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.
function onScroll() { console.log("Scroll position:", window.scrollY);}
// โ
run the handler at most once every 200msconst throttledScroll = throttle(onScroll, 200);
window.addEventListener("scroll", throttledScroll);Here is what each line is doing:
onScrollis the work we want to limit. It logs the current vertical scroll position fromwindow.scrollY.throttle(onScroll, 200)wrapsonScrollso it can run at most once every 200 milliseconds, and we store the wrapped version inthrottledScroll.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!
- Copy the
throttlefunction into a script. - Attach a throttled handler to the
scrollevent that logswindow.scrollY. - Scroll the page and watch how often the message appears in the console.
- Change the delay from
200to1000and notice how the updates slow down. - Replace
scrollwithmousemoveand 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
setTimeoutis 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.