Why won't my countdown timer start and stop?

28,792

Solution 1

Here you go, you just needed to make myTimer global. I also fixed a glitch where after resetting the timer, it won't show 5.

var myTimer;
   function clock() {
     myTimer = setInterval(myClock, 1000);
     var c = 5;

     function myClock() {
       document.getElementById("demo").innerHTML = --c;
       if (c == 0) {
         clearInterval(myTimer);
         alert("Reached zero");
       }
     }
   }
<p id="demo">5</p>
<button onclick="clock(); document.getElementById('demo').innerHTML='5';">Start counter</button>
<button onclick="clearInterval(myTimer);">Stop counter</button>

Solution 2

Quick and dirty answer

   var myTimer;
   function clock() {
     myTimer = setInterval(myClock, 1000);
     var c = 5;

     function myClock() {
       document.getElementById("demo").innerHTML = --c;
       if (c == 0) {
         clearInterval(myTimer);
         alert("Reached zero");
       }
     }
   }
<p id="demo">5</p>
<button onclick="clock()">Start counter</button>
<button onclick="clearInterval(myTimer)">Stop counter</button>

timer in your function (because its declared, var, inside your function) can only be accessed inside your function. Moving the var declaration outside your function makes it global.

Better solution

But putting things in the global scope is (mostly) a bad idea. So.....there's a better way:

   
var myTimerObj = (function(document){
   
   var myTimer;

   function start() {
     myTimer = setInterval(myClock, 1000);
     var c = 5;

     function myClock() {
       document.getElementById("demo").innerHTML = --c;
       if (c == 0) {
         clearInterval(myTimer);
         alert("Reached zero");
       }
     }
   }
   
   function end() {
       clearInterval(myTimer)
   }

   return {start:start, end:end};
 })(document);
<p id="demo">5</p>
<button onclick="myTimerObj.start()">Start counter</button>
<button onclick="myTimerObj.end()">Stop counter</button>

the better solution utilises a revealing module pattern and will hold the timer inside a private scope, Tl;Dr it stops the timer polluting the global scope.

Solution 3

myTimer is only in scope within the function. One solution is to make it global.

var myTimer;
function clock() {
     myTimer = setInterval(myClock, 1000);
     var c = 5;

     function myClock() {
       document.getElementById("demo").innerHTML = --c;
       if (c == 0) {
         clearInterval(myTimer);
         alert("Reached zero");
       }
     }
   }
<p id="demo">5</p>
<button onclick="clock()">Start counter</button>
<button onclick="clearInterval(myTimer)">Stop counter</button>
Share:
28,792
Tommi Tiihonen
Author by

Tommi Tiihonen

Updated on October 08, 2021

Comments

  • Tommi Tiihonen
    Tommi Tiihonen over 2 years

    I need to make a simple countdown timer from 5 to zero, with the buttons to START and STOP the counter. The only thing that I don't know is that why won't my counter stop.

    The code is presented below:

       function clock() {
         var myTimer = setInterval(myClock, 1000);
         var c = 5;
    
         function myClock() {
           document.getElementById("demo").innerHTML = --c;
           if (c == 0) {
             clearInterval(myTimer);
             alert("Reached zero");
           }
         }
       }
    <p id="demo">5</p>
    <button onclick="clock()">Start counter</button>
    <button onclick="clearInterval(myTimer)">Stop counter</button>

  • James Walker
    James Walker over 2 years
    all these timers go wonky when you start them with double clicks
  • Liam
    Liam over 2 years
    I don't think anyone suggested that this was a full solution. This is simply an answer about scopes