1

so I'm currently attending the fullstackOpen course of the University of Helsinki and while doing one of the exercises (it was about a redux function that shows and hides notifications) I stumbled across a concept that I'm confused with:

Let's say that I have a button that, when clicked, takes 2 seconds to print "click" on the console. If I use setTimeout to 'wait' for those two seconds, and, in the meantime, I click in the button again, the 'setTimeout' logic in the stack gets all buggy. The solution that I found was to create a "check" variable to control if the button was already clicked and, if so, it clearTimeout() before it sets the off time again.

It works well, but, until I got in the right solution, I was stuck trying to insert the "timeoutCheck" inside the function that would create the asynchronous code... why it only works if the variable is outside the scope of the function? Is there any better solution? I think I'm missing something.

Here is a ugly vanilla example of a situation like the one in course. I'm "simulating" a user clicking three times in a row in the button, and, if the variable is inside the function, we get a buggy situation, while if the variable is outside of the function, even if the user clicks three times in a row, just the first one is counted. I can provide the whole redux app if needed.

Code that doesn't work:

activateTime = () => {
    let timeoutCheck

    if(timeoutCheck){
        clearTimeout(timeoutCheck)
    }

    timeoutCheck = setTimeout(() => console.log('clicked'), 2000)
}

const button = document.createElement('button')
button.addEventListener('click', () => activateTime())
setTimeout(() => button.click(), 250)
setTimeout(() => button.click(), 350)
setTimeout(() => button.click(), 450)

Code that works:

let timeoutCheck

activateTime = () => {
    if(timeoutCheck){
        clearTimeout(timeoutCheck)
    }

    timeoutCheck = setTimeout(() => console.log('clicked'), 2000)
}

const button = document.createElement('button')
button.addEventListener('click', () => activateTime())
setTimeout(() => button.click(), 250)
setTimeout(() => button.click(), 350)
setTimeout(() => button.click(), 450)
  • because when it is inside it creates a new variable every time. – epascarello Jan 20 '21 at 20:15
  • If you declare the variable inside the function, you get a new variable every time you run the function, it doesn't have the value from the previous run. – Barmar Jan 20 '21 at 20:15
  • 1
    Does this answer your question? [What is the scope of variables in JavaScript?](https://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript) – Heretic Monkey Jan 20 '21 at 20:15

1 Answers1

0

Every time you call activateTime it initializes the variable timeoutCheck, so it will always will be undefined. You can try a closure like so:

const activateTimeClosure = () => {
 let timeoutCheck

 return {
   activateTime () {
    if(timeoutCheck){
        clearTimeout(timeoutCheck)
    }

    timeoutCheck = setTimeout(() => console.log('clicked'), 2000)
   }
 }
}
const { activeTime } = activateTimeClosure()
const button = document.createElement('button')

button.addEventListener('click', () => activateTime())
Filipe
  • 1,788
  • 2
  • 13
  • 18