Skip to content

Instantly share code, notes, and snippets.

@aungthuoo
Last active May 20, 2024 15:59
Show Gist options
  • Save aungthuoo/9f77db8e7f97dcd050b405245fec2000 to your computer and use it in GitHub Desktop.
Save aungthuoo/9f77db8e7f97dcd050b405245fec2000 to your computer and use it in GitHub Desktop.

What is Throttling?

Quick notes (Using JavaScript )

Js code

// throttling
let count = 0;
function printScroll() {
  count += 1;
  console.log("scroll called", count);
}

function throttle(fx, delay) {
  let timeoutId = null;
  return function () {
    if (!timeoutId) {
      timeoutId = setTimeout(() => {
        fx();
        clearTimeout(timeoutId);
        timeoutId = null;
      }, delay);
    }
  };
}

const throttleFn = throttle(printScroll, 2000);

document.addEventListener("scroll", (e) => {
  throttleFn();
});

HTML Code

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  </head>

  <body>
    <div class="div-element-aqua" style="height:300px">
      element 1
    </div>
    <div class="div-element-lime" style="height:300px">
      element 2
    </div>
    <script src="./app.js"></script>
  </body>
</html>

Quick notes (Using React.js )

const useThrottle = (func, delay) => {
  let timeout = null;
  return (...args) => {
    if (timeout) {
      return;
    }
    func(...args);
    timeout = setTimeout(() => {
      timeout = null;
    }, delay);
  };
};

export default useThrottle;

Now, inside the App component, call this method and pass the click handler handleClick() and a delay of 1000ms.

const handleClickThrottled = useThrottle(handleClick, 1000);

We'll use this function as the event handler for our button.

<button onClick={handleClickThrottled}>Click Me</button>

Detail explain

Throttling is a mechanism that allows a function execution for a limited number of times after that it will block its execution.

Simple words:- It limits the execution of your code to once in every specified time interval. It is a practice used to improve browser performance.

Throttling is a technique used to limit the rate at which a function is called. Throttling transforms a function such that it can only be called once in a specific interval of time.

Let's understand this with an example. Let's take a function fun():

function fun() {
    console.log('This is a function')
}

We want to modify this function so that it can only be called once in 500ms. So, throttling will take fun() as an input, and return a modified (throttled) function throttledFun()  that can only be executed 500ms after the previous function was executed.

When you call throttledFun() multiple times within 500ms, fun() will only be executed the first time. You will have to wait 500ms before fun() can be executed again. This happens after every subsequent function call. Thus, fun() can only be called once every 500ms.

How to Implement Throttling in JavaScript

Let's first understand what we want to achieve with throttling:

  • Call the function immediately the first time.
  • After each call, prevent the function from being called again for a certain time period.
  • Once that time period has passed, the function can be called again.

To do all this, let's first create a helper function that will return a throttled function:

function throttle(func, delay) {
      return () => {}   // return throttled function
}

For any use cases, the throttled function will be used instead of the original fun().

Let's start by simply calling the function like this:

function throttle(func, delay) {
  return () => {
        func()
    }
}

Once the function is called, we want to block it from being called again for a certain time period delay. Once the time has passed, we want to unblock the function. We can achieve this behaviour using setTimeout.

For now, let's keep the setTimeout empty. You'll understand how it works in a minute.

setTimeout(() => {}, delay)

Next, we'll declare a variable timeout that will be initialized only once in the outer function (that is the throttle() function). The setTimeout method returns a unique timeout id that we can use to identify a timeout. We'll assign the current timeout id to timeout.

function throttle(func, delay) {
    let timeout=null
    return () => {
        func()
        timeout=setTimeout(() => {
            // do something
        }, delay)
    }
}

Since timeout contains the id of the current timeout, we add a condition at the start of the throttled function to check if a timeout exists before calling the original function func().

function throttle(func, delay) {
    let timeout=null
    return () => {
        if(!timeout) {
            func()
            timeout=setTimeout(() => {
                // do something
            }, delay)
        }
    }
}

Initially, timeout is null, so the function is executed. The throttled function then starts a new timeout and assigns it to the timeout variable. In the next function call, it checks if a timeout exists before calling func(). If a timeout already exists, it does not execute func().

But what happens after the time period of delay has passed? Inside the setTimeout we need to do something that enables func() to be called again. Since we are using timeout to control the function calls, we set it to null after delay milliseconds.

timeout=setTimeout(() => {
    timeout=null
}, delay)

Now, when you call the function, it is executed and the process repeats by starting a new timeout. We have successfully throttled the function.

But there's something fundamental that we are still overlooking. In the current function call, once we assign setTimeout to the timeout variable, for the next one we are assuming that timeout is still valid and holds the value that we want – even if the variable is declared inside the throttle() function.

How is the inner function still able to have access to the variable long after the throttle() function has finished execution? It uses a concept called a closure. Let's take a quick detour to visit this concept.

Use Case of Function Throttling

Let's see how throttling is used in practical applications. We'll take a button that makes a call to the backend server when a user clicks it. An API call is made every time someone clicks the button.

But an API request can take some time, and if the user clicks the button again, or repeatedly in a short time, more and more API calls are made which could overload the server. To avoid this behaviour, we use function throttling. Let's implement this with React.

App Component

In the App component, let's create a button with an onClick handler that makes an API call to the Node server.

function App() {
  const fetchData = async () => {
    const resp = await fetch("http://localhost:8000/data");
    return resp.json();
  };
  const handleClick = () => {
    fetchData().then((data) => {
      console.log(data);
    });
  };

  return (
    <div className="App">
      <button onClick={handleClick}>Click Me</button>
    </div>
  );
}

export default App;

Now, let's click this button repeatedly.

Multiple API Calls

Implement Throttling using a Custom Hook

We'll write the throttling logic inside a custom hook. Since you may need throttling in multiple places in your application, it is recommended to put the logic inside a custom hook.

Create a new folder called custom-hooks. Inside it, create a file useThrottle.js. Inside the file, create and export new function useThrottle(). The method should take a function and delay as parameters and return the throttled function.

const useThrottle = (func, delay) => {
  let timeout = null;
  return (...args) => {
    if (timeout) {
      return;
    }
    func(...args);
    timeout = setTimeout(() => {
      timeout = null;
    }, delay);
  };
};

export default useThrottle;

Now, inside the App component, call this method and pass the click handler handleClick() and a delay of 1000ms.

const handleClickThrottled = useThrottle(handleClick, 1000);

We'll use this function as the event handler for our button.

<button onClick={handleClickThrottled}>Click Me</button>

Ref : throttling-in-javascript

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment