Throttling and debouncing are two popular and widely performed coding techniques that will help to improve the performance of JavaScript code that undergoes execution repeatedly within a certain period of time. In this tutorial, we’ll learn about the JavaScript Throttle and Debounce and how to implement them in our code to boost our code’s performance and write better and faster code in JavaScript.
Throttling and debouncing enable coders with control over the rate at which a method is called. They are especially useful when dealing with event handler assignments. We can take examples of scroll handlers, keyboard events, or even just clicking a button rapidly.
What is Throttle?
The throttle is a higher-order function that takes a method and a timeout function and only allows that function to be executed at most once per the amount of time specified. It is to ensure that the function is called at most once in a specified time period. This means throttling will stop a function from running if it has run just recently.
So, where do we use the Throttling technique?
- We use throttling in button clicks to prevent spam click.
- We can use throttling in an API call.
- The throttle can be used in a
mousemove
/touchmove
event handler.
Implementation of Throttle
First, let us take a simple example, which explains the code with and without the Throttle.
export class IncreaseTheNumber extends Component<{}, {num : number}> { state = {num: 0}; increase = () => { this.setState({num: this.state.num + 1}); } render() { return ( <div> {this.state.num} <div> <button onClick={this.increase}>Increment!</button> </div> </div> ); } }
In this example above, we have a state num
and a method that can increase this state increase
. There is a button we can click which increments num
. Here, we can click the Increment
button as quickly as we want and it will increment the num
state. Now consider we need to delay state num
to increase as quickly as we click on the button. So, we can use the throttle to slow down the increments. Check out the example below in which the throttle is implemented:
export class IncreaseTheNumber extends Component<{}, {num: number}>{ state = {num: 0}; increase= () => { this.setState({num: this.state.num + 1}); } } function throttle(func, timeout) { let exexute: true; return (...args) => { if (!execute) { return; } execute= false; func(...args); setTimeout(() => { execute = true; }, timeout); }; } increaseWithThrottle = throttle(this.increase, timeout); render() { return ( <div > {this.state.numSpells} <div> <button onClick={this.increase}>Increment</button> <button onClick={this.increaseWithThrottle}> Increment with Throttled </button> </div> </div> ); } }
Here, We now have a button called increaseWithThrottle
which implements the throttling technique and delays the increment of the num
state.
Now, we need to understand the throttle
method. The throttle
is a method that takes a function and a timeout. Throttle returns a new method that forms a closure around the original one.
Here, we need to keep track of a variable called execute
that prevents the inner method from executing unless the timeout has elapsed. If we execute the method we also fire a timeout that will set execute
to true when the timeout has elapsed. This is pretty much how we implement the Throttling in JavaScript.
Now, let’s move on Debounce!!
What is Debounce?
Basically, Debouncing is likely used more than Throttling. In many cases, you can have a better impact with debouncing than a Throttle.
Debounce is just a bit different from the Throttle. In case of a throttle, we slow down method calls as they happen. But in case of debounce, we don’t execute the method at all until the previous execution of that method has stopped. This seems like a more secure way from the coding concept.
It is really useful if we want to perform a computation or fetch an API when the user is done typing, scrolling or navigating.
So, where do we use the Debounce technique?
- We use debounce in a
resize
event handler. - We can use debounce in a
scroll
event handler. - Denounce can be used in auto-complete or auto-save features.
Implementation of Debounce
export class IncreaseTheNumber extends Component<{}, {num: number}>{ state = {num: 0}; increase= () => { this.setState({num: this.state.num + 1}); } } function debounce(func: Function, timeout: number) { let timer: NodeJS.Timeout; return (...args: any) => { clearTimeout(timer); timer = setTimeout(() => { func(...args); } ,timeout); }; } incrementWithDebounced = debounce(this.increase, timeout); render() { return ( <div > {this.state.numSpells} <div> <button onClick={this.increase}>Increment</button> <button onClick={this.incrementWithDebounced}> Increment with Debounce</button> </div> </div> ); } }
Using debounce function here, we’ll notice that we can click Increment with Debounce as many times as we like, but it will only execute after we’ve stopped clicking it. The code for this is similar to the previous Throttle component but only with debounce method.
Here, while the throttle relied on a simple true
or false
, with debounce, we need to maintain access to the timer. We implement the timer
from the Node module because we need to clear the previous timeout every time the method gets called again. We then set a new timeout method to call the inner method.
So, this is how the Debounce is implemented.
Hence, the overall concept of JavaScript Throttle and Debounce is completely covered in this article.