I have a stopwatch that has buttons to start, stop, and reset the time. I assigned an interval to a variable to pause it using clearInterval every time I click the stop button, but my interval is calling the function even though I clicked no button. How do I fix this?
const startButton = document.getElementById('start'); const stopButton = document.getElementById('stop'); const resetButton = document.getElementById('reset'); const myInterval = setInterval(setTime, 10); startButton.addEventListener('click', () => { setInterval(setTime, 10); }) stopButton.addEventListener('click', ()=> { clearInterval(myInterval); }) const timeUnits = ['00', '00', '00', '00']; milliSeconds = 0; seconds = 0; minutes = 0; hours = 0; function setTime() { if (minutes == 60) { hours++; minutes = 0; timeUnits[0] = hours; timeUnits[1] = 0; } else if (seconds == 60) { minutes++; seconds = 0; timeUnits[1] = minutes; timeUnits[3] = 0; } else if (milliSeconds == 100) { seconds++; milliSeconds = 0; timeUnits[2] = seconds timeUnits[3] = 0; document.getElementById('para').innerHTML = timeUnits.join(':'); } else { milliSeconds++; timeUnits[3] = milliSeconds; document.getElementById('para').innerHTML = timeUnits.join(':'); }; }
<p id="para">00:00:00:00</p> <button id="start">Start</button> <button id="stop">Stop</button> <button id="reset">Reset</button>
You set up the interval in two places:
const myInterval = setInterval(setTime, 10); // <-- Here (A)
startButton.addEventListener('click', () => {
setInterval(setTime, 10); // <-- and here (B)
})
In spot A (auto-start on page load) you save the interval ID into myInterval
so that you can later do clearInterval(myInterval)
.
However, in spot B (on-demand start on "start" button click), you do not do that, so the interval set by clicking the "start" button can never be cleared.
This can be fixed by saving the interval into myInterval
in both places:
let myInterval = setInterval(setTime, 10)
startButton.addEventListener('click', () => {
myInterval = setInterval(setTime, 10)
})
Now, this created a bit of duplicate code, which is not ideal, and also there is still the problem that just clicking "start" multiple times would create multiple intervals running in parallel, overwriting the previous interval ID with the new one, making the old intervals again unclearable.
My suggestion for solving both of these issues is to create functions startInterval
and stopInterval
, where startInterval
would also first call stopInterval
before setting up a new interval, and stopInterval
clearing the old one if it exists. Then you can call startInterval
both on page load and on "start" button click, and stopInterval
on "stop" button click:
let myInterval = null
function startInterval () {
stopInterval()
myInterval = setInterval(setTime, 10)
}
function stopInterval () {
if (!myInterval) return
clearInterval(myInterval)
myInterval = null
}
startInterval()
startButton.addEventListener('click', startInterval)
stopButton.addEventListener('click', stopInterval)
From the wording of the question I'm not sure whether you really want to auto-start the timer though. In case you don't, you can simply remove the startInterval()
line from my example (or in case of the original code, change the first assignment to let myInterval = null
like in the second example).
The reason your interval is automatically starting is because you call the setInterval
function when you assign the variable to begin with. To prevent this, simply define the variable with let myInterval = null;
so that you get the variable, but it doesn't automatically start the interval until the start button is pressed.
The reason it's not stopping when you press the "stop" button after pressing "start" is because in your startButton
click handler, you're not re-assigning the interval to the variable. So it's an interval that you can't clear because you didn't assign it to anything. The simple fix is to say myInterval = setInterval(setTime, 10)
. Since you are reassigning myInterval
you need to also define it with let
instead of const
.
const startButton = document.getElementById('start'); const stopButton = document.getElementById('stop'); const resetButton = document.getElementById('reset'); let myInterval = null; startButton.addEventListener('click', () => { myInterval = setInterval(setTime, 10); }) stopButton.addEventListener('click', ()=> { clearInterval(myInterval); }) const timeUnits = ['00', '00', '00', '00']; milliSeconds = 0; seconds = 0; minutes = 0; hours = 0; function setTime() { if (minutes == 60) { hours++; minutes = 0; timeUnits[0] = hours; timeUnits[1] = 0; } else if (seconds == 60) { minutes++; seconds = 0; timeUnits[1] = minutes; timeUnits[3] = 0; } else if (milliSeconds == 100) { seconds++; milliSeconds = 0; timeUnits[2] = seconds timeUnits[3] = 0; document.getElementById('para').innerHTML = timeUnits.join(':'); } else { milliSeconds++; timeUnits[3] = milliSeconds; document.getElementById('para').innerHTML = timeUnits.join(':'); }; }
<p id="para">00:00:00:00</p> <button id="start">Start</button> <button id="stop">Stop</button> <button id="reset">Reset</button>
This line:
const myInterval = setInterval(setTime, 10);
actually starts the interval.
You need to change it to this:
let myInterval;
startButton.addEventListener('click', () => {
myInterval = setInterval(setTime, 10);
})
This ensures that everytime you press the start
button the interval will be assigned to the myInterval
variable again which can then be cleared by the stop button
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.