3

I came across to find out how the debounce works after reading this: Can someone explain the "debounce" function in Javascript

In this there was something in the accepted answer that I couldnt figure out how it could be like that:

"Note that this overwrites the value of timeout and this value persists over multiple function calls!"

Every time the debounce method is called, it creates a new stack for it, and the returned function could access the timeout value. Yes I understood it as the nature of closure. But across multiple calls, we got the wrapper debounce will produce a new local timeout, so how can it be possible to clear the timeout in previous calls as they are not bound to the same timeout ?

Thanks a lot, I know this is very basic JS but I do not want to ignore it as I know, if understood it, I can understand more about JS.

Community
  • 1
  • 1

1 Answers1

7

What may be confusing you is that you don't call debounce() repeatedly. If you did, then yes, the timeout variable would be unique to each invocation.

What you do instead is call debounce() once. It returns a function which you then can call repeatedly. Because this function is nested inside debounce() alongside the timeout variable, each time you call it, it uses the same timeout variable.

David Walsh's article has an example:

var myEfficientFn = debounce( function() {
    // All the taxing stuff you do
}, 250 );

window.addEventListener( 'resize', myEfficientFn );

Note that we only call debounce() once here, and it returns a function which is saved as myEfficientFn. Then myEfficientFn gets called on every resize event, but the callback function passed into debounce() is only called after there are no more resize events for 250 milliseconds.

You could also write that code equivalently as:

window.addEventListener( 'resize', debounce( function() {
    // All the taxing stuff you do
}, 250 ) );

Here it may look like you're calling debounce() multiple times, but you aren't. It's only being called once, at the time you call addEventListener(). The actual event listener function here isn't debounce(), it's the function that debounce() returned.

Or, for more clarity, let's break it apart step by step and use better names:

// Called after at least one resize event has fired but 250 milliseconds
// have gone by without another resize event.
function handleResizeAfterIdle() {
    // All the taxing stuff you do
}

// Create a function with debouncing that can be used as a resize event
// listener. resizeListener will be called on *every* resize event,
// but handleResizeAfterIdle will be called only after 250 milliseconds
// have elapsed with no more resize events.
var resizeListener = debounce( handleResizeAfterIdle, 250 );

// Now we can add the event listener.
window.addEventListener( 'resize', resizeListener );
Michael Geary
  • 28,450
  • 9
  • 65
  • 75
  • But the event handler is set to debounce so every time the event is trigger, let say "click". Everytime I clicked, the debounce will be called again, isnt it ? Because right now I bind the debounce to the event handler. – minhtran612 May 10 '17 at 06:19
  • Can you add an example of the code you're talking about to the question? I'll take a look at it and see if I can help explain it - or see if you're using `debounce()` correctly. I also added a similar example to the answer. – Michael Geary May 10 '17 at 06:22
  • 2
    @minhtran612: *"Because right now I bind the debounce to the event handler."* that is wrong. You have to bind the function *returned* by `debounce`. – Felix Kling May 10 '17 at 06:25
  • @MichaelGeary thanks a lot, clearing out the fear that I miss something on closure – minhtran612 May 10 '17 at 06:35