stop setInterval only works one time, why?

Viewed 141

I need some help, stop button invoke clearInterval() and only works one time, whats wrong in the code?

var start = document.querySelector("#start");
var stop = document.querySelector("#stop");

window.addEventListener('load', () => {

  function intervalo() {
    var tiempo = setInterval(function() {
    console.log("Set interval ejecutado");
  }, 1500);
    return tiempo;
  }

  var tiempo = intervalo();
  
  stop.addEventListener("click", function() {   
    clearInterval(tiempo);
  });

  start.addEventListener("click", function() {
    intervalo();
  });
});
<button id="stop"> stop! </button>
<button id="start"> start! </button>

4 Answers

It looks like setInterval is being called numerous times and therefor causing multiple timers to occur simultaneously; a cleaner version would be:

let tiempo; 

const start = () => {
  console.log("starting...")
  if(!tiempo) {
    tiempo = setInterval(
      ()=> {console.log("interval")}
    , 1000)  
  }
}

const stop = () => {
  console.log("stopped")
  clearInterval(tiempo);
  tiempo = null; 
}
<button onclick="stop()"id="stop"> stop! </button>
<button onclick="start()" id="start"> start! </button>

Did you notice that var tiempo = setInterval(function() {..}) was declare inside function intervalo() ? So its scope is in intervalo function.

But another var tiempo = intervalo() is declare outside intervalo, two variables tiemp are different, that's why clearInterval(tiempo); doesn't work.

Why first time does it work? Because when DOM was loaded and emit event load once, inside that function you set var tiempo = intervalo(), and it was set one time only until you clear it. Next time clicking on start : outside tiempo wasn't set to anything.

The "fix" is simple: declare tiemp on the top of load callback, then set it equal intervalId return from setInterval.

var start = document.querySelector("#start");
var stop = document.querySelector("#stop");

window.addEventListener('load', () => {
  var tiempo;
  function intervalo() {
    //tiempo was declared in this function's closure
    tiempo = setInterval(function() {
    console.log("Set interval ejecutado");
  }, 1500);
  }

  
  stop.addEventListener("click", function() {   
    //tiempo was declared in this function's closure
    clearInterval(tiempo);
  });

  start.addEventListener("click", function() {
    intervalo();
  });
});

p/s: please read more about scope in javascript, especially closure.

your variable name is very confusing and you override previous setInterval id with newer one every time; so I suggest use a more clear naming structure to avoid such scenario;

var start = document.querySelector("#start");
var stop = document.querySelector("#stop");
var intervalRefId;
window.addEventListener('load', () => {

  function intervalo() {
    return setInterval(function() {
      console.log("Set interval ejecutado");
    }, 1500);
  }

  intervalRefId = intervalo();
  
  stop.addEventListener("click", function() {   
    clearInterval(intervalRefId);
  });

  start.addEventListener("click", function() {
    intervalRefId = intervalo();
  });
});
<button id="stop"> stop! </button>
<button id="start"> start! </button>

Because you set one time your variable tiempo you must set it again with your interval function

var start = document.querySelector("#start");
var stop = document.querySelector("#stop");

window.addEventListener('load', () => {

  function intervalo() {
    return setInterval(function() {
       console.log("Set interval ejecutado");
    }, 1500);
  }
  var timer = true;
  var tiempo = intervalo();
  
  stop.addEventListener("click", function() {   
    clearInterval(tiempo);
    timer = false;
  });

  start.addEventListener("click", function() {
    if(timer == false) {
       tiempo = intervalo();
       timer = true;
    }
  });
});
<button id="stop"> stop! </button>
<button id="start"> start! </button>

Related