Debouncing in JavaScript
Published: 2022-10-07 13:03:52

Imagine your web application makes requests to an API endpoint and each request has a price, debouncing the request operation may save you a great deal of money.

There are cases where you have long-running operations and these operations are in a position where they can be fired frequently by your application users. Such operations invoked continuously may affect the performance of your web application. 

Debouncing is a technique that ensures long-running operations are not fired so often. It delays the execution of that particular program.

A common example is a search operation that is fired whenever a user types a query in an input field. Debouncing the operation would mean waiting for the user to stop typing for a particular time (usually milliseconds) before running the search operation.

Let’s write a simple implementation here:

```jsx
function debounce(func, time = 300) {
  let timer;

  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => func.apply(this, args), time);
  };
}
```

Now we can create a mock project to see how this may function in a real application.

```jsx
<!-- index.html -->
<html>
  <head>
    <title>Mock Search Page</title>
  </head>
  <body>
    <label for="search">Enter your search</label>
    <input id="search" type="text" name="search" />
    <script>
      const nameElement = document.querySelector("#search");

      function debounce(func, time = 500) {
        let timer;

        return (...args) => {
          clearTimeout(timer);
          timer = setTimeout(() => func.apply(this, args), time);
        };
      }

      const debouncedSearchFunction = debounce((event) => {
        console.log("querying: " + event.target.value + "....");
      });

      nameElement.addEventListener("keyup", (event) => {
        debouncedSearchFunction(event)
      });
    </script>
  </body>
</html>
```

In the code above, `debounce` returns a function and keeps a local variable `timer` (they both form a closure). `timer` acts like a state to manage the timing. 

In the event listener callback, we call the function that is returned by `debouce` and, as we can see, the arguments in this function are passed to the `func` argument using the method `[Function.prototype.apply](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)`.

## Conclusion

As I mentioned in the introduction of this article, in a case where each of your requests to an API endpoint is paid and the operations can be fired by the actions of a user. Debouncing the operations can be done to create a form of throughput per time (milliseconds).

I recently got nominated for two categories in Noonies 2022 by Hackernoon. You can vote for me (Kayode Oluwasegun) as a sign of support using these two links:

- [https://www.noonies.tech/2022/emerging-tech/2022-hackernoon-contributor-of-the-year-automation](https://www.noonies.tech/2022/emerging-tech/2022-hackernoon-contributor-of-the-year-automation)
- [https://www.noonies.tech/2022/programming/2022-hackernoon-contributor-of-the-year-linux](https://www.noonies.tech/2022/programming/2022-hackernoon-contributor-of-the-year-linux)