Search code examples
javascriptsetintervalclearinterval

clearInterval Doesn't Work if setInterval is Inside of a Loop


If I initialize setInterval inside of a loop within a function, clearInterval doesn't work. I tried setting it to the name of the variable and then the function itself. There are plenty of questions about similar circumstances, but I couldn't find anything specific to this example.

The "Destroy Counter" function was only created so that it wouldn't run in an infinite loop.

let counterAnimation;
let stop_function = showCounter();

function showCounter() {
  const counter = document.createElement("span");
  counter.setAttribute("id", "cnt");
  counter.innerText = 0;
  document.getElementById("stop").insertAdjacentElement("afterend", counter);
  for (let i = 0; i < 5; i++) {
    counterAnimation = setInterval(() => {
      if (document.getElementById("cnt")) {
        document.getElementById("cnt").innerText =
          parseInt(document.getElementById("cnt").innerText) + i;
      }
    }, 250);
  }
}

function stopSetInterval() {
  clearInterval(counterAnimation);
  clearInterval(stop_function);
}

function destroyCounter() {
  if (document.getElementById("cnt")) {
    const element = document.getElementById("cnt");
    element.remove();
  }
}

 
<button id="start" onclick="showCounter()">Start</button>
<button id="stop" onclick="stopSetInterval()">Stop</button>

<br><br>
<button onclick="destroyCounter()">Destroy Counter</button><br>
<span style="font-family:sans-serif;font-size:0.6rem">Note: "Destroy Counter" created only because I couldn't get it to stop!


Solution

  • You are creating 5 timers, but your stop button is only clearing the last one you created. You will need to store all 5 timers and clear all 5.

    In this snippet I turned counterAnimation into an array, added a loop to the stop button to work through the array.

    I also added a check at the beginning of showCounter() so it works better if you press start multiple times.

    let counterAnimation = [];
    
    
    function showCounter() {
      // Only create the counter span if it has not already there
      if (!document.getElementById("cnt")) {
        const counter = document.createElement("span");
        counter.setAttribute("id", "cnt");
        counter.innerText = 0;
    
        document.getElementById("stop").insertAdjacentElement("afterend", counter);
      }
    
      for (let i = 0; i < 5; i++) {
        let counter = setInterval(() => {
          if (document.getElementById("cnt")) {
            document.getElementById("cnt").innerText =
              parseInt(document.getElementById("cnt").innerText) + i;
          }
        }, 250);
        counterAnimation.push(counter);
      }
    }
    
    
    function stopSetInterval() {
      for (let counter of counterAnimation) {
        clearInterval(counter);
      }
      // And clear the list
      counterAnimation = []
    }
    <button id="start" onclick="showCounter()">Start</button>
    <button id="stop" onclick="stopSetInterval()">Stop</button>
    
    <br><br>