javascript - 倒数计时器不循环工作和休息时间

标签 javascript typescript ionic-framework setinterval

我有一个“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>

Source
CanIuse #requestAnimationFrame

关于javascript - 倒数计时器不循环工作和休息时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57646073/

相关文章:

javascript - 从通用js文件访问Grails Controller 变量

ionic-framework - 当用户单击手机后退按钮时,ionic 4 处理模态

javascript - ionic 触发点击事件不起作用

Javascript:悬停元素,更改不相关元素中的类

javascript - 将阿拉伯日期值格式化为字符串 : new Date(). toLocaleDateString ('ar' ); => 'ddyyyy/m/'

带有 ngrx 存储的 Angular Rxjs 可观察链

typescript |不可变 |扩展 Immutable.Map 类型的正确方法

node.js - 如何在Node.js和TypeScript项目中使用URLSearchParams

javascript - ionic 。如何使用存储并获得真实结果

javascript - 用 bool 注解修饰 JS 对象