Home > Software engineering >  clearInterval does not seem to be working
clearInterval does not seem to be working

Time:08-01

I'm trying to make a simple javascript counter.

Basically, I'm getting an integer value from a user by input and I want to count descending from that value to 0.

So I coded this:

let inputCounter = document.querySelector("#input-counter");
let startBox = document.querySelector(".start-box");
let startCounter = document.querySelector("#start-counter");
let errorMessage = document.querySelector("#error-message");
let timerCircle = document.querySelector(".c100");
let timeSpan = document.querySelector(".c100 > span");

startCounter.addEventListener('click', function() {
  let seconds = inputCounter.value;
  if (isNaN(seconds)) {
    errorMessage.textContent = "Not an integer value";
    errorMessage.classList.add("active");
  } else {
    errorMessage.classList.remove("active");
    timerCircle.style.display = "block";
    startBox.style.display = "none";
    timeSpan.textContent = seconds;

    let timerId = setInterval(() => {
      seconds -= 1;
      if (seconds < 0) {
        clearInterval(timerId);
      }

      timeSpan.textContent = seconds;
    }, 1000);
  }
});
<div >
  <div >
    <input type="text" id="input-counter" placeholder="type your value in seconds">
    <button id="start-counter">Start</button>
    <div id="error-message"></div>
  </div>
  <div >
    <span></span>
    <div >
      <div ></div>
      <div ></div>
    </div>
  </div>
</div>

So this works fine and properly counts down from that custom entered number but the only problem here is that it goes to -1, -2, -3 and etc.

So that is why I tried determining timerId to the setInterval function and then checking this condition:

if(seconds < 0){
    clearInterval(timerId);
}

However it does not clear the interval and still shows Negative numbers...

So what's going wrong here? How can I properly clear the interval when it comes to 0?

CodePudding user response:

Try this code:

    let seconds = 10
    let timerId = setInterval(() => {
      
      if (seconds <= 0) {
        clearInterval(timerId);
      }

      console.log(seconds);
    seconds -= 1;
    }, 1000);

CodePudding user response:

Your clearInterval implementation works, but it is missing a return statement following the clear. So it clears the interval correctly (it won't run the setTimeout callback again) but the current execution of the callback continues, so it goes past the if statement and sets -1 in the label anyway. The return statement, halts the execution of that callback when you reach your base case, and leaves the label set to 0.

You could also re-arrange the code to set the label above the if statement, and change the condition to if (seconds === 0), so then following the clear and return, your seconds variable remains at 0, instead of -1.

let inputCounter = document.querySelector("#input-counter");
let startBox = document.querySelector(".start-box");
let startCounter = document.querySelector("#start-counter");
let errorMessage = document.querySelector("#error-message");
let timerCircle = document.querySelector(".c100");
let timeSpan = document.querySelector(".c100 > span");

startCounter.addEventListener('click', function() {
  let seconds = inputCounter.value;
  if (isNaN(seconds)) {
    errorMessage.textContent = "Not an integer value";
    errorMessage.classList.add("active");
  } else {
    errorMessage.classList.remove("active");
    timerCircle.style.display = "block";
    startBox.style.display = "none";
    timeSpan.textContent = seconds;

    let timerId = setInterval(() => {
      seconds -= 1;
      if (seconds < 0) {
        clearInterval(timerId);
        return; // THIS IS WHAT WAS MISSING
      }

      timeSpan.textContent = seconds;
    }, 1000);
  }
});
<div >
  <div >
    <input type="text" id="input-counter" placeholder="type your value in seconds">
    <button id="start-counter">Start</button>
    <div id="error-message"></div>
  </div>
  <div >
    <span></span>
    <div >
      <div ></div>
      <div ></div>
    </div>
  </div>
</div>

CodePudding user response:

If you stop when < 0, it will check:

  • 2, reduce, its now 1, its < 0? NO, so go again
  • 1, reduce, its now 0, its < 0? NO, so go again
  • 1, reduce, its now -1, its < 0? yes, stop: result -1

You can stop in < 1 or <= 0.
console.log(seconds) // 0

Additionally, working with timeout and numeric variables is not so accurate (depends on instabilities in processing).

I suggest saving the start time, and calculating the difference every second.

If the PC freezes for 3 seconds, when it starts up again, 3 seconds have passed and not just 1.


let inputCounter = document.querySelector("#input-counter");
let startBox = document.querySelector(".start-box");
let startCounter = document.querySelector("#start-counter");
let errorMessage = document.querySelector("#error-message");
let timerCircle = document.querySelector(".c100");
let timeSpan = document.querySelector(".c100 > span");

startCounter.addEventListener('click', function() {
  let seconds = inputCounter.value;
  if (isNaN(seconds)) {
    errorMessage.textContent = "Not an integer value";
    errorMessage.classList.add("active");
  } else {
    errorMessage.classList.remove("active");
    timerCircle.style.display = "block";
    startBox.style.display = "none";
    timeSpan.textContent = seconds;

    let timerId = setInterval(() => {
console.log({seconds})
      seconds -= 1;
      if (seconds < 1) {
        clearInterval(timerId);
      }

      timeSpan.textContent = seconds;
    }, 1000);
  }
});
<div >
  <div >
    <input type="text" id="input-counter" placeholder="type your value in seconds">
    <button id="start-counter">Start</button>
    <div id="error-message"></div>
  </div>
  <div >
    <span></span>
    <div >
      <div ></div>
      <div ></div>
    </div>
  </div>
</div>

  • Related