-2

Here is a simple counting code to count from 14 to 0 using setInterval. After 3 seconds I want to clear the interval and stop counting using savedTimerCounter('stop');. The problem is I can't access the interval to clear it at savedTimerCounter('stop');

Why and how to fix this? What I'm missing?

let savedTimer;

function savedTimerCounter(el) {
  //function scope variable 
  switch (el) {
    case 'start':
      timeleft = 14;
      console.log(timeleft);
      savedTimer = setInterval(function() {
        timeleft--;
        console.log(timeleft);
        if (timeleft <= 0) {
          clearInterval(savedTimer);
          console.log("done");
          return;
        }
      }, 1000);
      break;
    case 'stop':
      clearInterval(savedTimer);
      break;
  }
}

//Start counting 
savedTimerCounter('start');

//Stop counting that dosn't work!
setTimeout(function() {
  savedTimerCounter('stop');
}, 3000)

If you put the let savedTimer; outside of the function (Why?) the code works but as it's a bad practice to create global variables I want a hint here...

j08691
  • 204,283
  • 31
  • 260
  • 272
Sara Ree
  • 3,417
  • 12
  • 48
  • 2
    First off: why make that function pull double duty? Just stick with clear code and have a separate `startTimer()` and `stopTimer()`. That said, the reason is "because that's how variable scoping in Javascript, and many other languages, works". If you put your variable in the function, it stops existing when the function exits. The next time you call the function, it would create a _new_ variable with the same name, in that new call's execution scope. Google "javascript variable scoping" and read up on it, because you're not going to write a lot of working code without understanding scoping. – Mike 'Pomax' Kamermans Dec 17 '19 at 17:06
  • 1
    In addition, despite "bad practice" label for use of global variable in general procedural and OO programming, sometimes and in some languages it makes sense to use them. JavaScript and particularly this code is a good example. You can use `savedTimer` as an argument for `savedTimerCounter` to avoid using globals, but this is not typical practice in this case and you may keep global. This is up to you. In OO scenario you'd create a class field shared by all class members. – Anatoliy R Dec 17 '19 at 17:20

1 Answers1

1

your problem is the scope of the variable, lets take this example:

function doSomething(action) {
  let timer;
  console.log(timer) // will be always undefined;
  // now I do something
  switch (action) {
    case 'start':
      {
        timer = 'start';
        break;
      }
    case 'end':
      {
        timer = 'end'
        break;
      }
  }

  console.log(timer) // will be always the case that enters.
}

doSomething('start'); // this is one function call
console.log('-----------');
doSomething('end'); // this is another function call

as you can see, you are doing 2 calls to the same function, but they are not using the same variables. each variable that you define inside is different.

you can check this post What is the scope of variables in JavaScript? that will help you understand your problem.

Prince Hernandez
  • 3,623
  • 1
  • 10
  • 19