Javascript 倒计时计时器不在工作和休息期间循环

Javascript 倒计时计时器不在工作和休息期间循环,javascript,typescript,ionic-framework,setinterval,Javascript,Typescript,Ionic Framework,Setinterval,我有一个“tabata”计时器。到目前为止,它经历了一个准备阶段,然后是工作阶段,最后是休息阶段。在休息阶段之后,我想多次重新循环工作和休息阶段 但是,在rest阶段结束时,对work phase函数的调用不起作用 使用下面的代码时,我在console.log中遇到以下错误 错误类型错误:无法设置未定义或空引用的属性“intervalOne” 错误类型错误:无法获取未定义或空引用的属性“restTime” 我以同样的方式使用setInterval,所以我不明白为什么这次它不起作用 为什么我的代码

我有一个“tabata”计时器。到目前为止,它经历了一个准备阶段,然后是工作阶段,最后是休息阶段。在休息阶段之后,我想多次重新循环工作和休息阶段

但是,在rest阶段结束时,对work phase函数的调用不起作用

使用下面的代码时,我在console.log中遇到以下错误

错误类型错误:无法设置未定义或空引用的属性“intervalOne”

错误类型错误:无法获取未定义或空引用的属性“restTime”

我以同样的方式使用setInterval,所以我不明白为什么这次它不起作用

为什么我的代码没有循环

在整个代码中,我将分离函数放在了不同的地方,我去掉了设置间隔以消除错误,但当然这会停止计数器倒计时!我不知所措

   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)
        }
      }
    }
  }
重复(事件){
this.intervalOne=setInterval(()=>this.begin(this.countdown,this.tabata),1000)
}
开始(myCountdown,myTabata){
let first=document.querySelector(“#counter”);
this.set=this.set;
如果(this.set==1){
this.countdown=myCountdown-1;
这是倒计时>0
如果(这是倒计时<10){
this.countdown=“0”+this.countdown;
}
first.innerHTML=this.countdown;
如果(this.countdown==0){
clearInterval(这是intervalOne);
this.intervalTwo=setInterval(()=>work(),1000)
首先,classList.remove('orange');
}
让intervalTwo=this.intervalTwo;
让secondCount:any=+myTabata.split(':')[1];
职能工作(){
如果(秒计数<10){
secondCount=“0”+secondCount;
}
secondCount=secondCount-1;
二次计数>0;
first.innerHTML=secondCount;
if(secondCount==0){
间隔时间(间隔2);
first.classList.remove('green');
首先,classList.remove('orange');
secondCount=+myTabata.split(':')[1];
this.intervalOne=setInterval(()=>rest(),1000)
console.log(secondCount);
}
}
让interval=this.intervalOne;
让myRest=this.restime;
函数rest(){
如果(myRest<10){
myRest=“0”+myRest;
}
myRest=myRest-1;
myRest>0;
first.innerHTML=myRest;
如果(myRest==0){
间隔时间;
myRest=this.restTime;
this.intervalTwo=setInterval(()=>work(),1000)
}
}
}
}

简单地说,不要使用setInterval,而且不要在循环中询问DOM

在每个循环中都使用querySelector。 , 在读取DOM时,浏览器正在解析整个文档以获取所请求的值

这在一次准时的情况下是可以的,但在循环中,这会严重减慢你的间歇时间。当循环花费的时间超过间隔时,浏览器将简单地扩展间隔循环,以继续渲染。这就是问题所在。几分钟后,这甚至可以冻结标签和整个计算机

我们现在可以使用快速循环

使用,比较开始日期和当前日期。这比询问DOM要快得多

下面是一个例子,这与您的要求非常接近。您应该能够根据自己的具体需要对其进行修改

/*秒到(字符串)HH:MM:SS.MS-----------------------*/
功能扇区计数器(秒){
设o=新日期(0)
设p=新日期(秒*1000)
返回新日期(p.getTime()-o.getTime()).toString().split(“”[4]+“+p.getMillimes())
}
let job,origin=new Date().getTime()
常量计时器=()=>{
作业=请求动画帧(计时器)
OUT.textContent=secToTimer((新日期().getTime()-origin)/1000)
}
requestAnimationFrame(计时器)
span{font-size:4rem}


重置 重新启动
停止
谢谢您深思熟虑的回答。然而,你让我大吃一惊,我不知道如何在我的代码中实现这一点。我将在YouTube上搜索reqquestAnimationFrame()函数的更多示例。。。干杯。是的,这有点令人不安:),不用担心,这只是一个带回调的函数,在这个例子中,它在回调上调用自己,这创建了循环。然后,浏览器以视频卡/屏幕的帧速率循环,通常为60FPS。这是未来的必经之路!