Throttling function calls in JavaScript


You’re at a water park in line for your favorite water slide. Only one person is allowed to go down the slide every 15 seconds. This is implemented for safety. If every person when right after the other, we would have backups in the slide or injuries with people crashing into each other at the bottom. This is an example of throttling.
In programming, throttling can be described as limiting the amount of function invocations where invocations are coming in at a continuous pace. In simpler terms, only allowing a function to be called at most once in a defined time frame, say, 1 second.
Non-throttled example
In JavaScript, throttling can be a common use case for functions that are called while the page is scrolling or resizing. In our examples, we’ll be using scroll events.
Scroll events will fire as often as every pixel scrolled. If you have an expensive function to run, but it has to run as the page scrolls, you could see how quickly this could be an issue.
function logScroll(name) {
const date = new Date();
console.log(name + " scrolling at " + date.getTime());
}
window.addEventListener("scroll", () => {
logScroll("test")
});
In the example above, we run the logScroll function while the window is scrolling. This will cause this function to run many times as we scroll through the page. Notice how the often the function is called by looking at the console while scrolling.
How to create a throttle function
Let’s take a look at how to actually create a function that will throttle the amount of times this logScroll function is called.
function throttle(func, limit = 1000) {
let timer = null;
return (...args) => {
if (timer) return;
func(...args);
timer = setTimeout(() => {
timer = null;
}, limit);
};
}
We create two parameters: func and limit. Func is the function that we be calling at the throttled rate and limit is the minimum amount of time between function calls.
Inside the throttle function, we set a timer variable with a value of null. This timer will hold time timeout to wait until func can be called again. It’s set to null by default because func is required to be called first before a timeout can be started.
We then return a function inside throttle (this is a closure) that will be used to handle the actual logic behind the throttle. Inside the closure we:
First, we check if timer has a value. If it does, we return early. This is because the setTimeout has been set as timer’s value and is currently running. If that’s the case, we don’t want to call func, so we return early.
Next, we call func with the arguments (if they exist). When we create the variable to hold the throttle function, we’ll pass any variables that func needs at that time. In our example, logScroll requires a name, so that name will be passed to func when this throttle is created.
Finally, we set the value of setTimeout to the timer variable. The setTimeout will run as long as the limit we setup in the parameters. At the end of the limit, timer will be set to null. This allows us to call func again because the throttle will have finished blocking new invocations to func.
Let’s look at our updated scroll event with this new throttle:
const throttledLog = throttle(logScroll, 1000);
window.addEventListener("scroll", () => {
throttledLog("test")
});
Since throttle is a closure, we’ll need to store throttle in it’s own variable which itself is a function (the function that gets returned in throttle). Remember above when I said that the args passed to the closure will be the arguments passed to the created throttle function? Here, we see throttledLog is getting the argument test
which will be passed down to logScroll as it’s name argument.
Since our throttle is set to only allow one function call every second (1000ms), our logScroll function is only logging to the console every second. This is the throttle doing it’s magic!
Maybe for your use case 1 second is too long or possibly not long enough. You’ll want to make sure it’s dialed in for your use case. Regardless, I hope you can see the power behind throttling and how it can be used to really help the efficiency and possibly even the cost of your website.
Subscribe to my newsletter
Read articles from Brad Preston directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Brad Preston
Brad Preston
I'm a software developer with a background in Golang and JS/TS