A throttle is a common technique used in the browser to improve an application's performance by limiting the number of events your code needs to handle. You should use a throttle when you want to execute a callback at a controlled rate, allowing you to handle intermediate states repeatedly at each fixed interval of time.
On the left, side we have normal events that aren't throttled and the event handler is executed each moment the page is scrolled. On the right, we have a throttled event handler and will only execute the function once every 1 second.
A throttle is a cousin of the debounce, and they both improve the performance of web applications. However, they are used in different cases. A debounce is utilized when you only care about the final state. For example, waiting until a user stops typing to fetch typeahead search results. A throttle is best used when you want to handle all intermediate states but at a controlled rate. For example, track the screen width as a user resizes the window and rearrange page content while it changes instead of waiting until the user has finished.
Write a function
throttle that takes a callback function and a
delay time and limits the callback from executing to once for each window of
If the function is executed multiple times,
throttle should handle it every
delay milliseconds in evenly spaced increments.
You only care about the most recent event and should ignore any previous ones if a new value comes in.
Throttling in the Context of Web Development
Imagine you have a scroll event handler where you want to display new content to a user as they move down the page. If we executed the callback every time the user scrolls a single pixel, we would quickly get clogged with events if they rapidly scroll because it would send hundreds or thousands of events in quick succession. Instead, we throttle it so that we only check the distance scrolled every 100ms so that we're getting only 10 callbacks per second. The response will still feel instantaneous to the user but be much more efficient computationally.
A throttle creates evenly-spaced function calls. Imagine if you were performing some heavy calculation or an API request in the event handler callback function. By throttling these callbacks, you prevent the app from freezing or unnecessarily hammering your server with requests.
Let's immediately jump into the code for a throttle. I'll describe it below and then also provide a commented version of the function.
A throttle is a higher-order function, which is a function that returns another function (named
throttledEventHandler here for clarity).
This is done to form a closure around the
storedEvent function parameters.
This preserves the values of each variable to be read when
throttledEventHandler is executed.
The following is a definition of each variable:
callback: The throttled function that you want to execute at a given rate.
delay: The amount of time you want the throttle function to wait between executions of the
throttleTimeout: The value used to indicate a running throttle created by our
storedEvent: The event that you want to handle with the throttled
callback. This value will continually be updated until the throttle ends. Then it will execute
callbackwith the most recent value.
We can use our throttle as in the following code:
Since a throttle returns a function, the
throttledEventHandler from the first example and the
returnedFunction function from the second example are actually the same function. Every time a user scrolls, it will execute
Let's step through what happens when we throttle a function. First we create a closure around variables so they will be available to
throttledEventHandler on every execution.
throttledEventHandler receives 1 argument which is the event. It stores this event in the
Then we check if we have a timeout running (ie. an active throttle). If we do have a throttle, then
throttledEventHandler has completed this execution and waits to execute the callback. If the throttle is not active, we are able to immediately handle the event with our callback function. We then call
setTimeout and store the timeout value which indicates our throttle is running.
While the timeout is active, the most recent event is always stored. The callback execution is bypassed which saves us from performing CPU intensive tasks or calling our API.
setTimeout finishes, we null out the
throttleTimeout indicating that the function is no longer throttled and can handle events. If there is a
storedEvent, we want to handle it immediately, and to do this we call
throttledEventHandler recursively. The recursive call inside the
setTimeout is what allows us to handle events at a constant rate. It will repeatedly execute the same process after a desired delay as long as new events continue to come in.
See a throttle in action and play around with it in this Codepen.
A commented version of the function as well:
Table of Contents