我有一个“tabata”计时器。到目前为止,它通过准备阶段倒计时,然后是工作阶段,最后是休息阶段。在休息阶段之后,我想重新循环几次工作和休息阶段。
但是,在rest phase结束时,调用work phase function不起作用。
使用以下代码时,我在 console.log 中收到以下错误...
错误类型错误:无法设置未定义或空引用的属性“intervalOne”
错误类型错误:无法获取未定义或空引用的属性“restTime”
我以同样的方式使用 setInterval,所以我不明白为什么这次它不起作用。
为什么我的代码没有循环?
我在整个代码中将单独的函数放在不同的位置,我去掉了 setIntervals 以消除错误,但当然这会停止计数器倒计时!我很茫然。
repeat(event) {
this.intervalOne = setInterval(() => this.begin(this.countdown, this.tabata), 1000)
}
begin(myCountdown, myTabata) {
let first = document.querySelector('#counter');
this.set = this.set;
if (this.set == 1) {
this.countdown = myCountdown - 1;
this.countdown > 0
if (this.countdown < 10) {
this.countdown = "0" + this.countdown;
}
first.innerHTML = this.countdown;
if (this.countdown == 0) {
clearInterval(this.intervalOne);
this.intervalTwo = setInterval(() => work(), 1000)
first.classList.remove('orange');
}
let intervalTwo = this.intervalTwo;
let secondCount: any = +myTabata.split(':')[1];
function work() {
if (secondCount < 10) {
secondCount = "0" + secondCount;
}
secondCount = secondCount - 1;
secondCount > 0;
first.innerHTML = secondCount;
if (secondCount == 0) {
clearInterval(intervalTwo);
first.classList.remove('green');
first.classList.remove('orange');
secondCount = +myTabata.split(':')[1];
this.intervalOne = setInterval(() => rest(), 1000)
console.log(secondCount);
}
}
let interval = this.intervalOne;
let myRest = this.restTime;
function rest() {
if (myRest < 10) {
myRest = "0" + myRest;
}
myRest = myRest - 1;
myRest > 0;
first.innerHTML = myRest;
if (myRest == 0) {
clearInterval(interval);
myRest = this.restTime;
this.intervalTwo = setInterval(() => work(), 1000)
}
}
}
}
最佳答案
简单地说,不要使用setInterval,也不要在循环中询问DOM。
您在每个循环中都使用了 querySelector。 , 读取 DOM 时,浏览器正在解析整个文档以获取请求值。
这在准时的“一次性”情况下没问题,但在循环中,这会大大减慢你的间隔。当循环花费的时间超过间隔时,浏览器将简单地延长间隔循环,以继续渲染。这就是问题所在。像这样几分钟后,这甚至可以卡住选项卡和整个计算机。
我们现在可以使用 requestAnimationFrame用于快速循环。
使用 Date object , 比较开始日期和当前日期。这比询问 DOM 快得多。
这是一个示例,这与您的要求非常接近。您应该能够根据您的确切需要对其进行修改。
/* Seconds to (STRING)HH:MM:SS.MS -----------------------*/
function secToTimer(sec){
let o = new Date(0)
let p = new Date(sec * 1000)
return new Date(p.getTime()-o.getTime()).toString().split(" ")[4] + "." + p.getMilliseconds()
}
let job, origin = new Date().getTime()
const timer = () => {
job = requestAnimationFrame(timer)
OUT.textContent = secToTimer((new Date().getTime() - origin) / 1000)
}
requestAnimationFrame(timer)
span {font-size:4rem}
<span id="OUT"></span>
<br>
<button onclick="origin = new Date().getTime()">RESET</button>
<button onclick="requestAnimationFrame(timer)">RESTART</button>
<button onclick="cancelAnimationFrame(job)">STOP</button>
关于javascript - 倒数计时器不循环工作和休息时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57646073/