Throttling vs Debouncing in Javascript

Throttling vs Debouncing in Javascript

ยท

4 min read

Throttling and debouncing after two terms that are often mistaken with each other. Both of these terms are crucial when it comes to building optimized web apps and interfaces. Believe it or not, it is very easy to understand the distinction between the two! This blog will help you clear all your doubts that you may have regarding the differences between the two. So let's dive in!

  1. What is Throttling first of all?

    Throttling is simply a way of "rate limiting" the number of times a function is called. Let us take an example here. Suppose you have a CTA (Call to Action) button on your front end. This button makes a function call to let's say, fetch an API. Now a user (which we assume here is a little dumb๐Ÿ˜‚) presses that button and expects a result on his screen. Unfortunately, he sees no visual feedback of his query being processed but the click has been registered and his query is in the process of being resolved but the user, thinking that he might not have pressed the button at all, goes on to press that button again. He again sees no visual cue to know that his query is being worked upon and clicks the same button 4 more times out of frustration. Let us try to understand what happens here. The system had to make 6 function calls for a task that required only one. This may not sound like a lot but do keep in mind that we are only talking about one user at a time. Just imagine a website having hundreds of buttons and thousands of concurrent users having to deal with thousands of unnecessary function calls. Inadvertently, this will cause performance issues and this is where the need for a throttling function rises.

    Throttling is a technique in which no matter how many times the user clicks that button, the attached function will be executed only one time in a particular time frame. It ensures that the function call is only made at regular intervals.

    A tutorial isn't a tutorial without some code ๐Ÿ˜ˆ

const throttle = (func, limit) => {
    let lastFunc;
    let lastRan;
    return function() {
        const context = this;
        const args = arguments;
        if (!lastRan) {
            func.apply(context, args);
            lastRan = Date.now();
        } else {
            clearTimeout(lastFunc);
            lastFunc = setTimeout(function() {
                if ((Date.now() - lastRan) >= limit) {
                    func.apply(context, args);
                    lastRan = Date.now();
                }
            }, limit - (Date.now() - lastRan));
        }
    };
};
  1. Now what is debouncing then?

    Debouncing is a technique where you delay executing a function call until after a certain amount of time has passed. This is especially useful when you have a frequently used function and you do not want it to trigger after each subsequent event as that may cause performance issues. It's time for another example! Suppose you are shopping for your favorite keyboard from an e-commerce site. Now, in the search bar, you type the name of your keyboard. Let's say the name is "HyperX Alloy Origins Core". Now for this query, by default, the search function will be triggered on each keydown event, since there are 27 characters here, it will be searched for 27 times! 27 times for a search that probably only needed 3 or 4 searches. As one can probably tell by now, this is not very efficient and causes bottlenecks which only grows as our application starts to scale.

    Now, to mitigate this, we use a debounce function that has a delay which delays the execution of the function till that delay has expired. In this particular example, we delay the execution of our search function on the keydown event, so that instead of firing up for every keydown event, it fires up only 3 or 4 times. This massively helps in making the performance of your web app much better. Time for some more code!


const debounce = (func, delay) => {
    let timeoutId;
    return function() {
        const context = this;
        const args = arguments;
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => {
            func.apply(context, args);
        }, delay);
    };
};
const debouncedFunc = debounce(() => {
    console.log('Debounced function is executed');
}, 500);
for (let i = 1; i <= 5; i++) {
    setTimeout(debouncedFunc, i * 200);
}

In conclusion, debouncing and throttling are both useful techniques for managing function invocation frequency, but they serve different purposes. Debouncing delays function execution until after a specified period of inactivity, while throttling limits the rate at which a function can be invoked. Depending on the specific use case and requirements, one may choose to use either debouncing or throttling to optimize performance and user experience.

Did you find this article valuable?

Support Anubhav Adhikari by becoming a sponsor. Any amount is appreciated!

ย