# Creating "debounce()" Using a Closure

A `debounce()` function is one of those awesome tools that we reach for when we want to delay an action from taking place too rapidly.

A good use case might be trying to prevent too many API calls to your server when a user types into a search input box and an API call is fired for every key press. There may be some use cases where we want to immediately respond like this, but in many situations, we probably want to delay for a split second and check that the user hasn't in fact typed anything additional.

We can do this using a `debounce()` function. Each time we respond to an action, we wait for say 500ms and check that no more actions have been made before responding.

We'll first create a simple `debounce()` function to understand how it actually debounces an action. Then we'll look into `closures` and how they can help improve the implementation of `debounce().`

### A Simple `debounce()` function

This simple implementation of the `debounce()` function uses three parameters.

* `callback()` - the function that is called when the delay is over
    
* `currentId` - which holds a reference to the current delayed action
    
* `delay` - in miliseconds.
    

```javascript
function debouce(callback, currentId, delay){
  window.clearTimeout(currentId);
  newId = window.setTimeout(function(){
      callback.apply();
  }, delay);
  return newId;
}
```

Each time the `debounce()` function is called, it will cancel any unresolved timeouts that have been passed in with the reference of `currentId`. It then creates a new timeout which is stored in the `newId` variable. The new timeout will then call the `callback` function when the delay is finished, providing it is not cancelled by calling `debounce()` again. We make the `newId` timeout reference available to the calling scope by returning the value of `newId`.

In the editor below, we can see that we have first defined a `timeoutId`. This is passed to `debounce()` function call along with the `sayHello` callback and a delay of `2000`. We have then reassigned the value of `timeoutId` the value that we return from the `debounce()` function.

<iframe height="300" width="100%" src="https://codepen.io/anjalani/embed/QWPKmwN?default-tab=js,result&amp;editable=true&amp;theme-id=dark">
  See the Pen <a href="https://codepen.io/anjalani/pen/QWPKmwN">
  Creating "debounce()" Using a Closure:Part 1</a> by Anja Lani (<a href="https://codepen.io/anjalani">@anjalani</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>

The console shows the following results:

```plaintext
debounced
debounced
debounced
hello
```

The word `debounced` is logged 3 times immediately and then 2 seconds later the word `hello` is logged.

Each time the `debounce()` function is called it cancels the previous timeout and sets up a new timeout to call the callback function after the delay.

This is a fairly simple solution, but it requires the `timeoutId` from any previous timeouts to be stored and passed to the `debounce()` function each time it is called.

We can develop a much cleaner and encapsulated approach using a closure.

### A Close Look at Closures in JavaScript

Let's start with a definition of what `closures` are in JavaScript.

> A **closure** is the combination of a function bundled together (enclosed) with references to its surrounding state (the **lexical environment**). In other words, a closure gives you access to an outer function's scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time. [MDN: Closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures)

Nothing like a concrete example to help us understand what that means. Look at the example in the editor below.

We define a function `myFunc` (the outer function) which performs three tasks:

* logs out the word `constructed`
    
* sets an initial value of `count = 0`
    
* returns an anonymous function (the inner function)
    

We then call the `myFunc()` function and set its return value to the variable `myFuncInstance`

<iframe height="300" width="100%" src="https://codepen.io/anjalani/embed/zYXKWGp?default-tab=js,result&amp;editable=true&amp;theme-id=dark">
  See the Pen <a href="https://codepen.io/anjalani/pen/zYXKWGp">
  Creating "debounce()" Using a Closure: Part 2</a> by Anja Lani (<a href="https://codepen.io/anjalani">@anjalani</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>

Looking at what is logged to the console, we can see that only the word `constructed` is logged to the console. The inner anonymous function is not called, it is only returned.

\*Uncomment the next line so that we can see the value of `myFuncInstance`\*

The value logged is:

```plaintext
function(){
    count++;
    console.log('called',count);
}
```

So the line `const myFuncInstance = myFunc();` is in fact defining a new [function expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function).

```javascript
const myFuncInstance = function(){
    count++;
    console.log('called', count); 
}
```

At this point, our new function expression has not been called, although we have defined it by calling `myFunc()`.

At this stage, we have not done much more than return a function from a function. It does get interesting now as we look at the special behaviour of closures in JavaScript.

*Uncomment the next three lines so that we are calling the myFuncInstance() three times.*

Our console now logs:

```plaintext
constructed
function(){
    count++;
    console.log('called',count);
}
called 1
called 2
called 3
```

Each time we have called the `myFuncInstance()` function, we have been able to keep track of the value of `count` and correctly increment it.

This feels a bit strange for two reasons.

* Why doesn't the `count` value get set back to 0 each time?
    
* It seems that `myFuncInstance()` shouldn't have access to the value of `count` . Why don't we get `undefined` for the value of count as?
    

The reason for both of these behaviours is because of closures.

The `myFunc()` function is only actually called once and this is why the value is only set to `0` when we call `const myFuncInstance = myFunc();`

Again looking at our original `myFunc()` definition. We can see that in the function definition, the inner function does in fact have access to the value of `count` from the parent (outer) function When we call `myFunc()` and return the inner anonymous function, the inner function encloses the value of `count` and maintains its reference to this variable. Then every time we call `myFuncInstance()` this reference to the current value of `count` is correctly maintained.

```javascript
function myFunc () {
  console.log('constructed');
  let count = 0;
 
  return function(){
    count++;
    console.log('called',count);
  };
}
```

This makes using closures a great way for calling functions and maintaining their state without needing to rely on any external variables.

### debounce() with a closure

As we have just seen using a closure can help us to fully encapsulate the logic of a function without needing to refer to external variables..

```javascript
function debounce(callback, wait){
  let timeoutId = null;
  return function(...args){
    window.clearTimeout(timeoutId);
    timeoutId = window.setTimeout(() => {
      callback(...args);
    }, wait);
  };
}
```

The first thing that is obvious is that we are not passing in the `currentId` of the current timeout. Instead, we create a closure whereby we define the `timeoutId` only once and then return a function that creates a closure around the `timeoutId` variable.

```javascript
function sayHello(boy, girl){
   console.log(`Hello ${boy} & ${girl}`);
}

const debounced = debounce(sayHello, 5000);

debounced('Jack','Jill');
debounced('Sam', 'Maisy');
debounced('Peter', 'Jane');
```

Similar to the closures example that we looked at in the last section, we use a function expression to create our `debounced`() function.

```javascript
const debounced = debounce(sayHello, 5000);
```

This time instead of calling the `debounce()` function multiple times, we instead call the newly created `debounced()` function.

This allows us to call the `debounced()` function without needing to keep track of the `timeoutId`, this has now been cleanly handled by the closure that we have created inside the `debounce()` function.

We have also added the ability to pass values to the `debounced()` function. When we return the anonymous function from the `debounce()` function definition, we have added `...args` as a parameter to this function. This takes any parameters that are passed into the `debounced()` function `debounced(A,B,C)` and stores them in a new array.

We then have the option to use this array and either call this as the second parameter on the `apply()` method.

```javascript
callback.apply(null, args);
```

Or alternatively, we can use the `...args` with the spread operator and pass this directly on the `callback()` function call.

```javascript
callback(...args);
```

*Have a play around with the editor below*

<iframe height="300" width="100%" src="https://codepen.io/anjalani/embed/gOyweaV?default-tab=js,result&amp;editable=true&amp;theme-id=dark">
  See the Pen <a href="https://codepen.io/anjalani/pen/gOyweaV">
  Creating "debounce()" Using a Closure: Part 3</a> by Anja Lani (<a href="https://codepen.io/anjalani">@anjalani</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
