Reputation: 61
Can someone help me understand how this code snippet is going to work?
In geeks from greeks they have following code snippet
<html>
<body>
<button id="debounce">
Debounce
</button>
<script>
var button = document.getElementById("debounce");
const debounce = (func, delay) => {
let debounceTimer
return function() {
const context = this
const args = arguments
clearTimeout(debounceTimer)
debounceTimer
= setTimeout(() => func.apply(context, args), delay)
}
}
button.addEventListener('click', debounce(function() {
alert("Hello\nNo matter how many times you" +
"click the debounce button, I get " +
"executed once every 3 seconds!!")
}, 3000));
</script>
</body>
</html>
From the following Difference Between throttling and debouncing a function, it says, emit only if there is no pending action (and after specific second) Answer
Here I can't see any if condition to check if there is a pending action.
From the article they say
> If the debounce button is clicked only once, the debounce function
> gets called after the delay. However, if the debounce button is
> clicked once, and again clicked prior to the end of the delay, the
> initial delay is cleared and a fresh delay timer is started. The
> clearTimeout function is being used to achieve it.
So everytime the button is clicked, the timer is cleared and a new timer is started (and probably the new action is also triggered), which probably doesn't sound anything like what I read from SFO answer
Also, Can someone please also explain how func.apply(context, args), delay)
is used or code-line by line?
Upvotes: 1
Views: 205
Reputation: 7676
Here I can't see any if condition to check if there is a pending action.
There is no explicit checking done instead the 3 second is the max window that will be used to decide anything.
From the quoted answer at https://stackoverflow.com/a/57524083
Debounce (1 sec): Hi, I am that ^^ robot's cousin. As long as you keep pinging me, I am going to remain silent because I like to reply only after 1 second is passed since last time you pinged me. I don't know, if it is because I have an attitude problem or because I just don't like to interrupt people. In other words, if you keeping asking me for replies before 1 second is elapsed since your last invocation, you will never get a reply. Yeah yeah...go ahead! call me rude.
So if there was a click action and 3s has elapsed you run the event handler function, in short it is sort of "piggybacking". Pools in all your demands then gives it a go at once when it is sure that you won't be asking anymore
Regarding the 2nd part func.apply(context, args), delay)
- this is used because of the nature of scoping in javascript. In your example they haven't used anything related to the concept of this
keyword but just add this line this.innerText = 'hello'
after the alert, you would expect the text of button to change to "hello" and indeed it would work. But now replace func.apply(context, args)
with func(args)
and it wouldn't work...
Why? Because of the nature of this
keyword, it is inferred based on the place where the function is called from and NOT from the place where it is in inside the source code
So when after 3s setTimeout
calls this function () => func( args)
, this
points to setinterval
and you know this.innerText = 'hello'
doesn't make any sense on setInterval object(Yes everything is an object in javascript even functions too!)
What apply does is it allows you to manipulate the this
context that will be "resolved" inside a given function upon its invocation; doesn't matter where your desired function lies whether inside a class, an object or simply in global scope, as long as it's reachable you can pass it your arguments and an object that it will assume as its this
function fullName(greeting) {
alert(greeting + ', ' + this.firstName + " " + this.lastName);
}
var person1 = {
firstName: "John",
lastName: "Doe"
}
var person2 = {
firstName: "Santiago",
lastName: "Adan"
}
fullName.call(person1, "hello");
fullName.call(person2, "hola");
Upvotes: 1