Need a Website or app? Hire an experienced team of Web and Mobile developers with us.
Free Consultation

De-bounce and Throttle (JavaScript Edition)

How to debounce and throttle in JavaScript

Posted by Premjeet Prasad on 03 Jun 2022
De-bounce and Throttle (JavaScript Edition)

In primitive times, websites were simple. They were static, only used to read documents by genius people.

Back in present times, websites are more than just document readers, they are full of interactive elements, like clicking a button, using page scrolling to trigger some functionality, using resizing of browser to change the layout, animation, and whatnot.

Today internet is accessible to a lot more people than it used to be, and when these many individuals come into the picture it becomes hard to predict how each one of them will interact with the website.

For example, we have a button on our web page, and clicking on it will fetch random data from an API and display it, also assume that data fetching is not instant and take a few seconds.

Below is the demo which you can try. ( In this we will use setTimeout method to simulate a data fetching operation from an API )

https://codepen.io/prem-jeet/pen/JjpGLPz?editors=1010

In an ideal universe, the user will click the button, wait for data to be fetched and displayed, then if needed interact with the button again.

But I am pretty sure this ain’t no ideal universe, and by curiosity, you must have clicked the button multiple times, between the duration of the first click and data fetch. If you are an ideal user and haven’t done so, go ahead and click the button as rapidly as possible and see what happens to the data.

You will observe, that if the button is clicked multiple times, all the clicks are registered, the API is called multiple times, and the data gets overwritten repeatedly by the latest data fetched by the last click/clicks.

This is not good for both the API and the UI. As each click will fire an HTTP request and this requires data and bandwidth, which in turn could overload the API. Also Updating the page is expensive, and we will be doing it multiple times in a short time frame. This is a BIG NO No! and We need a way to handle such behavior.

One way is to disable the button on the first click and then re-enable it when the task is done, but user experience wise this is not good, as the user likes to interact and we are taking that power away from it.

We need a better solution, that lets the user think he has the control, but in actuality, we are the ones in control.

This is where De-bounce and Throttle come into play, these are two strategies, that deal with rapid action events, and handle them in different ways. Let's have a look at them one at a time.

De-bounce

Let’s understand De-bounce in simple terms.

Say we click a button, and an action is triggered that takes 500ms, if we click the button again within this 500ms then a new action will be triggered, in this case, we will see our actions pile up and happen one after another just like in the example in Why? Section.

We can think of a trivial solution as follow if within this 500ms the action is triggered again than we can cancel the previous action. This will make it so that at the end only one action is performed which is the last click 500ms ago.

In JavaScript, De-bounce can be implemented by leveraging the power of Closures and using Higher-Order functions that take in parameters :

  1. Action to be performed ( usually a function ).
  2. Delay / De-bounce time.

The first parameter to the De-bounce function is the function that we want to convert to a De-bounce version. This function can be something that gets triggered when the user clicks on a button.

The second parameter is the De-bounce time. This time decides the delay i.e the time required for the action to be performed.

Below is a simple example of the De-bounce function in JavaScript.

/*
  @param : fn => the function to convert
  @param : time => the time delay for debounce
*/
function debounce(fn, delay) {
  let timer = null

  return (...args) => {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => fn(...args), delay)
  }
}

// some function that gets triggered on button click
const clickHandler = () => {
  /* Perform some action*/
}

// De-bounce version of the clickHandler Function
const debouncedClickHandler = debounce(clickHandler, 500)

The De-bounce function returns a function, this returned function is a wrapper for our provided function. When we call this wrapper function for the first time(say on a button click), It uses the setTimeout method to delay the action (the delay parameter is the time in milliseconds) and stores the timeout id in the timer variable.

If within the provided delay time, the function is triggered again, it will first check if some action is already pending i.e whether the timer variable has some value or not. If some action is pending, it will clear it and trigger new action with a new timer.

Let's see this in action in the below example.

https://codepen.io/prem-jeet/pen/oNEbPjB?editors=1000

Throttle

Throttle is somewhat different from De-bounce.

Assume that on clicking a button some action is performed after 200ms, For both *****De-bounce* and Throttled version of this, click the button once, wait for 200ms, and the action will be performed, but the difference in both the concepts will come into play when we click the button multiple times within this 200ms time frame.

For De-bounce, this is the basic algorithm

  1. Click the button, and a timer for 200ms starts.
  2. If the button is not clicked in this 200ms time frame, then the action is performed at the end of 200ms.
  3. else the button is clicked, in the 200ms time frame, the timer is reset, the previous action is not performed and a new timer will be set and new action if any. Then GO TO STEP 2.

In summary, the action is performed after 200ms from the last click.

Now let’s see what Throttle does

  1. Click the button, and a timer for 200ms starts.
  2. If the button is not clicked in this 200ms time frame, then the action is performed at the end of 200ms.
  3. else the button is clicked, in the 200ms time frame, the click is not registered, the timer continues, and action is performed at the end of 200ms.

So basically, Throttle is a version of disabling the button but without disabled it visually**.**

In summary, say in a time frame of 1000ms where the throttling is set to 200ms and the user is clicking the button every 1ms, only 5 clicks will be registered i.e at [0ms, 201ms, 401ms, 601ms, 801ms] respectively,

Below is a simple example of a Throttle function implemented in JavaScript

/*
  @param : fn => the function to convert
  @param : time => the time delay for throttle
*/
function throttle(fn, delay) {
  let wait = false

  return (...args) => {
    if (!wait) {
      wait = true
      setTimeout(() => {
        fn(...args)
        wait = false
      }, delay)
    }
  }
}

// some function that gets triggered on button click
const clickHandler = () => {
  /* Perform some action*/
}

// De-bounce version of the clickHandler Function
const throttledClickHandler = debounce(clickHandler, 500)

Let's see this in action in the below example.

https://codepen.io/prem-jeet/pen/MWQVXQR?editors=1010

Conclusion

Both De-bounce and Throttling have their uses.

De-bouncing is a good method for controlling events that require rapid user actions such as typing in an input field or clicking a button. In the case of a search bar that makes API calls according to user input, implementing a De-bounce is a good way to reduce the number of calls made to the API.

Throttle is useful for cases where the user is carrying out a smooth or continuous event such as scrolling or resizing. In the event of animating elements based on their scroll position or handling an infinite scroll page, we can use the throttle to control how often the scroll handler is called.

Depending on our needs we can choose whatever suits the requirement.


Need a Website or app? Hire an experienced team of Web and Mobile developers with us.
Free Consultation

Related Services.



Hire ReactJS Developers
Hire Gatsby Developers
Hire NextJS Developers

We support the Open Source community.



Have a Project in mind?