'Trouble with setInterval() and clearInterval() while creating a pomodoro timer
I've been learning javascript for the last few months, so I am a rookie. Longtime reader, first time poster. The full code for what I'm working on is available here in this codepen
https://codepen.io/dconnenc/pen/yLpwrQO?editors=1011
I'm hitting a pretty bad wall.
My current problem is keeping my clock maintaining proper mm:ss format, and getting it to tick down to 00:00.
min = min < 10 ? "0" + min : min;
sec = sec < 10 ? "0" + sec : sec;
I had been using the above, but it became too fragile inside of the interval function and begin adding 0s at the start at every interval. I have a fix so that it stops adding zeroes, but now it only ticks down to 0:00, and never reaches 00:00.
sessionTime = sessionTime < 10 && !sessionTime.toString().startsWith("0") ? "0" + sessionTime : sessionTime;
sec = sec < 10 && !sessionTime.toString().startsWith("0") ? "0" + sec : sec;
I've got stop for the day, and take a break, but a larger snippet of the code is below, and of course the link to the full codepen is above.
function timer() {
//ticks down timer
if(sec > 0){
sec--;
} else if (sec == 0 && sessionTime == 0) {
console.log("check");
document.getElementById('time-left').textContent = breakTime + ":" + sec;
} else if (sec == 0) {
sessionTime--;
sec = 59;
}
//mm:ss format (started running into an error with the interval returning extra 0s)
sessionTime = sessionTime < 10 && !sessionTime.toString().startsWith("0") ? "0" + sessionTime : sessionTime;
sec = sec < 10 && !sessionTime.toString().startsWith("0") ? "0" + sec : sec;
//updates display
document.getElementById('time-left').textContent = sessionTime + ":" + sec;
}
Solution 1:[1]
Try this with the min then with the seconds
if(sessionTime.toString().length === 1){
if(sessionTime === 0){
sessionTime = sessionTime;
}else{
sessionTime = "0"+sessionTime;
}
}
Solution 2:[2]
This implements the expected behavior of your timer (Using a 500ms interval and 3 second "minutes") using a somewhat minimized example. Session Time is hardcoded to 3 minutes.
Mixing strings and integers in JavaScript can easily lead to coding issues like the ones you have experienced, especially when trying to use the + operator on mixed strings and integers. Best to avoid that in your control variables and lead with an obvious string when you're setting displays.
let oneSecond = 500;
let oneMinute = 3;
let sessionTime = 3;
var secondsRemaining;
var intervalId;
function reset() {
console.log('check')
clearInterval(intervalId);
intervalId = 0
}
function start() {
secondsRemaining = sessionTime * oneMinute;
setTimeLeft()
intervalId = setInterval(timer, oneSecond)
}
function timer() {
if ( --secondsRemaining <= 0 ) {
reset()
}
setTimeLeft()
}
function setTimeLeft() {
document.getElementById('time-left').textContent = `${(''+ ~~(secondsRemaining / oneMinute)).padStart(2, '0')}:${(''+ secondsRemaining % oneMinute).padStart(2, '0')}`;
}
start()
<span id='time-left'></span>
This version handles multiple timers.
let oneSecond = 500;
let oneMinute = 3;
let sessionTime = 3;
function Timer(seconds, resetCallback, updateCallback, period) {
this.s = seconds;
this.p = period || oneSecond;
this.callback = resetCallback || Function.prototype;
this.update = updateCallback || Function.prototype;
this.reset = function() {
this.intervalId = clearInterval(this.intervalId)
this.callback()
}
this.start = function() { this.update(this.s); this.intervalId = setInterval(this.timer.bind(this), [ this.p ]) }
this.timer = function() { if (--this.s <= 0) this.reset(); this.update(this.s) }
}
function setTimeLeft(sec, id) {
document.getElementById(id || 'time-left').textContent = `${(''+ ~~(sec / oneMinute)).padStart(2, '0')}:${(''+ sec % oneMinute).padStart(2, '0')}`;
}
document.addEventListener("DOMContentLoaded", function() {
new Timer(sessionTime * oneMinute, () => console.log('check 1000ms'), setTimeLeft, 1000).start()
new Timer(6 * oneMinute, () => console.log('check 500ms'), (s) => { setTimeLeft(s, 'time-left2')}, 500).start()
new Timer(15 * oneMinute, () => console.log('check 300ms'), (s) => { setTimeLeft(s, 'time-left3')}, 200).start()
})
<span id='time-left'></span><br />
<span id='time-left2'></span><br />
<span id='time-left3'></span>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Ingenious_Hans |
| Solution 2 |
