One of the perils of listening to scroll events is performance degradation. The browser will execute the callback every single time the user scrolls, which can be many events per second. If the callback performs a bunch of repaints, this means bad news for the end user. Repaints are expensive, especially when you are redrawing large parts of the view, such as is the case when there is a scroll event.
The example below illustrates the issue:
See the Pen Unthrottled Scroll Events by SitePoint (@SitePoint) on CodePen.
Apart from performance degradation and being prone to causing seizures. This example illustrates what happens when the computer does exactly what you tell it to do. There is no smooth transition between background colors and the screen just flickers. Any hapless programmer may feel as if there is no hope left in this world. Isnʼt there a better way?
Regulating Events
One solution is to defer events and manage a bunch of them at once. There are two commonly used functions that can help us with this: throttle and debounce.
Throttle guarantees a constant flow of events at a given time interval, whereas debounce groups a flurry of events into one single event. One way to think about it is throttle is time-based and debounce is event driven. Throttling guarantees execution while debounce does not once grouping has occurred. If you want to know the specifics, check out this in-depth discussion of debounce versus throttling.
Debounce
Debounce solves a different problem, such as key presses with Ajax. When you type in a form, why would you send a request per keystroke? A more elegant solution is to group a burst of keystrokes into one event that will trigger the Ajax request. This fits within the natural flow of typing and saves server resources. With key presses, the interval between events isn’t important, since users donʼt type at a constant rate.
Throttle
Since there are no guarantees with debounce, the alternative is to throttle the scroll events. Scrolling occurs on a given time span, so it is fitting to throttle. Once the user begins scrolling, we want to guarantee execution on a timely basis.
This technique helps with checking if we are at a specific part of the page. Given the size of the page, it takes many seconds to scroll through content. This enables throttling to fire the event only once at any given interval. Event throttling will make the scrolling experience smoother and guarantee execution.
Below is a poor manʼs event throttler in vanilla JavaScript:
function throttle(fn, wait) {
var time = Date.now();
return function() {
if ((time + wait - Date.now()) < 0) {
fn();
time = Date.now();
}
}
}
This implementation sets a time
variable, which tracks when the function is first called. Each time the returned function is called it checks if the wait
interval has passed and if so it fires the callback and resets time
.
See the Pen Vanilla JS Throttle Implementation by SitePoint (@SitePoint) on CodePen.
Using a Library
Event throttling has many perils and it is not recommended to cook one up in-house. Rather than writing your own implementation, I recommend using a 3rd party implementation.
lodash
lodash is the de-facto standard for event throttling in JavaScript. This library is open source so feel free to explore the code. What is nice is the library is modular so it is possible to grab just what you need from it.
Scroll event throttling becomes simple with lodash’s throttle function:
window.addEventListener('scroll', _.throttle(callback, 1000));
This limits the flurry of incoming scroll events to one every 1,000 milliseconds (one second).
The API offers a leading
and trailing
option as such:
_.throttle(callback, 1, { trailing: true, leading: true });
These options determine whether the callback gets executed on the leading and / or trailing edge.
One gotcha here is if you specify leading and trailing set to false
, the callback does not fire. Setting the leading to true
will begin callback execution immediately and then throttle. When you set both leading and trailing to true
, this guarantees execution per interval.
Check out the demo on CodePen: Throttling Scrolling Events
What I find interesting from looking at the source code is that throttle()
is just a wrapper around debounce()
. Throttling just passes a different set of parameters to change the desired behavior. Throttle sets a maxWait
that guarantees the execution once it waits that long. The rest of the implementation remains the same.
I hope you find lodash beneficial in your next event throttling adventure!
Conclusion
The key to throttle vs debounce is to look at the nature of the problem you are to solve. The two techniques are suitable for different use cases. What I recommend is to look at the problem from the userʼs perspective to find the answer.
The beauty of using lodash is it abstracts a ton of complexity in a simple API. The good news is you can use _.throttle()
in your projects without having to add the whole library. There is lodash-cli, a tool that lets you create a custom build with only the functions that you need. Event throttling is only a tiny fraction of the entire library.
Frequently Asked Questions (FAQs) about Throttling Scroll Events
What is the purpose of throttling scroll events in JavaScript?
Throttling scroll events in JavaScript is a technique used to optimize the performance of a website or web application. When a user scrolls on a webpage, the browser generates a scroll event for each pixel of movement. This can lead to hundreds or even thousands of events being generated per second, which can significantly slow down the performance of the webpage. By throttling these events, we can limit the number of events that are processed, thereby improving the performance and responsiveness of the webpage.
How does throttling work in JavaScript?
Throttling in JavaScript works by setting a delay between the execution of events. When an event is triggered, a timer is started. If another event is triggered before the timer ends, it is ignored. This ensures that a certain amount of time must pass before another event is processed. This technique is particularly useful for events that are triggered frequently, such as scroll events.
What is the difference between throttling and debouncing?
Both throttling and debouncing are techniques used to limit the number of times a function can be executed over time. The main difference between the two lies in how they handle the delay. Throttling ensures that a function is not called more than once every X milliseconds, while debouncing ensures that a function is not called until X milliseconds have passed since the last time it was called. In other words, throttling executes the function at regular intervals, while debouncing executes the function after a period of inactivity.
How can I implement throttling in JavaScript?
Implementing throttling in JavaScript can be done using the setTimeout
function. This function allows you to delay the execution of a function by a specified number of milliseconds. By using setTimeout
in conjunction with an event listener, you can ensure that the event handler function is not called more than once every X milliseconds.
Can I use throttling with other events besides scroll events?
Yes, throttling can be used with any type of event in JavaScript, not just scroll events. It is particularly useful for events that are triggered frequently or that require a significant amount of processing, such as mouse move events, resize events, and key press events.
Are there any libraries or frameworks that provide built-in support for throttling?
Yes, there are several libraries and frameworks that provide built-in support for throttling. For example, Lodash, a popular JavaScript utility library, provides a throttle
function that makes it easy to implement throttling. Similarly, jQuery, a popular JavaScript library, provides a throttle
function as part of its API.
What are the potential drawbacks of throttling?
While throttling can improve the performance of a webpage, it can also lead to a less responsive user experience if not used properly. For example, if the delay is set too high, the user may notice a lag between their actions and the response of the webpage. Therefore, it’s important to find a balance between performance and responsiveness when using throttling.
How can I test the effectiveness of throttling?
You can test the effectiveness of throttling by measuring the performance of your webpage before and after implementing throttling. This can be done using browser developer tools, which provide detailed information about the performance of your webpage, including the time it takes to process events.
Can throttling be used in conjunction with other performance optimization techniques?
Yes, throttling can be used in conjunction with other performance optimization techniques, such as debouncing and requestAnimationFrame. By combining these techniques, you can further improve the performance and responsiveness of your webpage.
Are there any alternatives to throttling?
Yes, there are several alternatives to throttling, including debouncing and requestAnimationFrame. Debouncing is similar to throttling, but instead of limiting the number of times a function can be called over time, it ensures that a function is not called until a certain amount of time has passed since the last time it was called. RequestAnimationFrame is a method that tells the browser to perform an animation and requests that the browser call a specified function to update an animation before the next repaint.
![Camilo Reyes](https://uploads.sitepoint.com/wp-content/uploads/2015/04/1429479245wephoto-resize_lg-96x96.jpg)
Husband, father, and software engineer from Houston, Texas. Passionate about JavaScript and cyber-ing all the things.