我的程序中的JavaScript计时器以不可预知的方式停止

我的程序中的JavaScript计时器以不可预知的方式停止,javascript,Javascript,我是一个完全的初学者,我在业余时间写代码。谁能给我解释一下为什么有时候我的波莫多尔钟在0点1分时卡住了。(小时、分钟、秒) 我可以在chrome中的一个选项卡中启动它,它将在不可预知的周期数下工作,然后在开始下一个周期之前,它将毫无理由地停止在0 1。我希望它能连续工作(工作、休息、工作、休息等),直到我按下重置按钮 在JS中有更好的处理时间的方法吗 代码: //代码包装在闭包中以避免全局变量 (功能(){ 让我们倒计时; 让timeIsRunnig=false; 让actionTypeSwit

我是一个完全的初学者,我在业余时间写代码。谁能给我解释一下为什么有时候我的波莫多尔钟在0点1分时卡住了。(小时、分钟、秒)

我可以在chrome中的一个选项卡中启动它,它将在不可预知的周期数下工作,然后在开始下一个周期之前,它将毫无理由地停止在0 1。我希望它能连续工作(工作、休息、工作、休息等),直到我按下重置按钮

在JS中有更好的处理时间的方法吗

代码:

//代码包装在闭包中以避免全局变量
(功能(){
让我们倒计时;
让timeIsRunnig=false;
让actionTypeSwitch=“工作”;
const timerDisplay=document.querySelector(“.display\uu time-left”);
const infoDisplay=document.querySelector(“.display\u info”);
const endTime=document.querySelector(“.display_uend-time”);
const buttons=document.queryselectoral(“[数据时间]”);
const breakSettings=document.queryselectoral(“.settings\uu breakButton”);
const workSettings=document.querySelectorAll(“.settings\uuuu workButton”);
const breakValue=document.querySelector(“valueBreak”);
const workValue=document.querySelector(“valueWork”);
const buttonMain=document.querySelector(“#buttonMain”);
让workValueSettings=25;//默认的工作会话值(以分钟为单位)
让breakValueSettings=5;//默认的中断会话值(以分钟为单位)
workValue.textContent=workValueSettings+'min';
breakValue.textContent=breakValueSettings+'min';
timerDisplay.textContent=`${workValueSettings}:00`;
infoDisplay.textContent=“准备好了吗?”;
endTime.textContent=“按开始键”;
功能计时器(秒){
//清除任何现有计时器
清除间隔(倒计时);
//当前时间(毫秒)
const now=Date.now();
常量未来=现在+秒*1000;
显示TimeLeft(秒);
displayEndTime(未来);
函数timeCalc(){
const secondsLeft=Math.round((future-Date.now())/1000);
//检查我们是否应该停止它
如果(秒英尺<0){
清除间隔(倒计时);
返回;
}
//展示它
显示timeleft(secondsLeft);
}
倒计时=设置间隔(timeCalc,1000);
}
函数startTimer(){
常数秒=工作值设置*60;
actionTypeSwitch=“工作”;
infoDisplay.textContent=“努力工作!”;
计时器(秒);
}
函数startBreak(){
常数秒=breakValueSettings*60;
actionTypeSwitch=“Break”;
infoDisplay.textContent=“Short break!”;
计时器(秒);
}
函数resetTimer(){
常数秒=工作值设置*60;
//清除任何现有计时器
清除间隔(倒计时);
//刷新显示
显示TimeLeft(秒);
infoDisplay.textContent=“准备好了吗?”;
endTime.textContent=“按开始键”;
}
函数startAndReset(){
让name=“开始”;
if(timeIsRunnig==false){
timeIsRunnig=true;
name=“重置”;
this.innerHTML=名称;
startTimer();
}否则{
timeIsRunnig=false;
name=“开始”;
this.innerHTML=名称;
重置计时器();
}
}
函数playSoundStartBreak(){
//返回文档中的第一个元素
//与指定的选择器组匹配的。
const audio=document.querySelector(`audio[data-sound=“workDone”]`);
if(!audio)return;//停止函数运行
audio.currentTime=0;//倒带到开始位置
音频播放();
}
函数playSoundBackToWork(){
//返回文档中的第一个元素
//与指定的选择器组匹配的。
const audio=document.querySelector(`audio[data-sound=“backToWork”]`);
if(!audio)return;//停止函数运行
audio.currentTime=0;//倒带到开始位置
音频播放();
}
函数显示TimeLeft(秒){
恒时=浮点数(数学下限(sec/3600));
const minutes=parseFloat(数学层(sec/60));
const remainderMinutes=parseFloat(分钟数%60);
const remainderSeconds=parseFloat(秒%60);
日志(小时、剩余分钟、剩余秒);
//当计时器达到0时播放声音
如果(秒)==0){
如果(actionTypeSwitch==“工作”){
playSoundStartBreak()
startBreak();
}否则{
playSoundBackToWork();
startTimer();
}
}
//小时数为0时隐藏小时数
让hoursFirstStatement=hours<10?“0”:“;
让hoursSecondStatement=小时;
让冒号=“:”;
如果(小时==0){
hoursFirstStatement=“”;
hourssondstatement=“”;
冒号=”;
}
//此`${}`允许在字符串中添加javascript变量
常量显示=`${hoursFirstStatement}${hoursSecondStatement}${colon}${
剩余分钟数<10?“0”:“}${remainderMinutes}:${
remainderSeconds<10?“0”:“}${remainderSeconds}`;
timerDisplay.textContent=显示;
document.title=display++(“+actionTypeSwitch+”);
}
函数displayEndTime(时间戳){
const end=新日期(时间戳);
const hours=end.getHours();
const minutes=end.getMinutes();
endTime.textContent=`此会话在${hours<10?“0”结束:“}${hours}:${
分钟数<10?“0”:“}${minutes}”;
}
函数changeBreakSettings(){
const breakChangeValue=parseInt(this.dataset.settings);
如果((breakValueSettings=30&&breakChangeValue==1)){
return;//满足此条件时不执行任何操作
}否则{
breakValueSettings=breakValueSettings+breakChangeValue;
breakValue.textContent=breakValueSettings+'min';
}
}
函数更改工作设置(){
const workChangeValue=parseInt(this.dataset.settings);
如果((workValueSettings=120&&workChangeValue==1)){
return;//满足此条件时不执行任何操作
}否则{
workValueSettings=工作值
// Code wrapped in a closure to avoid global variables
(function () {
  let countdown;
  let timeIsRunnig = false;
  let actionTypeSwitch = "Work";

  const timerDisplay = document.querySelector(".display__time-left");
  const infoDisplay = document.querySelector(".display__info");
  const endTime = document.querySelector(".display__end-time");
  const buttons = document.querySelectorAll("[data-time]");
  const breakSettings = document.querySelectorAll(".settings__breakButton");
  const workSettings = document.querySelectorAll(".settings__workButton");
  const breakValue = document.querySelector("#valueBreak");
  const workValue = document.querySelector("#valueWork");
  const buttonMain = document.querySelector("#buttonMain");

  let workValueSettings = 25; // Default work session value in min
  let breakValueSettings = 5; // Default break session value in min

  workValue.textContent = workValueSettings + ' min';
  breakValue.textContent = breakValueSettings + ' min';

  timerDisplay.textContent = `${ workValueSettings}:00`;
  infoDisplay.textContent = "Are you ready?";
  endTime.textContent = "Press START";

  function timer(seconds) {
    // Clear any existing timers
    clearInterval(countdown);
    // Current time in ms
    const now = Date.now();
    const future = now + seconds * 1000;
    displayTimeLeft(seconds);
    displayEndTime(future);

    function timeCalc() {
      const secondsLeft = Math.round((future - Date.now()) / 1000);
      // Check if we should stop it
      if (secondsLeft < 0) {
        clearInterval(countdown);
        return;
      }
      // Display it
      displayTimeLeft(secondsLeft);
    }
    countdown = setInterval(timeCalc, 1000);
  }

  function startTimer() {
    const seconds = workValueSettings * 60;
    actionTypeSwitch = "Work";
    infoDisplay.textContent = "Working hard!";
    timer(seconds);
  }

  function startBreak() {
    const seconds = breakValueSettings * 60;
    actionTypeSwitch = "Break";
    infoDisplay.textContent = "Short break!";
    timer(seconds);
  }

  function resetTimer() {
    const seconds = workValueSettings * 60;
    // Clear any existing timers
    clearInterval(countdown);
    // Refresh display
    displayTimeLeft(seconds);
    infoDisplay.textContent = "Are you ready?";
    endTime.textContent = "Press START";
  }

  function startAndReset() {
    let name = "START";
    if (timeIsRunnig === false) {
      timeIsRunnig = true;
      name = "RESET";
      this.innerHTML = name;
      startTimer();
    } else {
      timeIsRunnig = false;
      name = "START";
      this.innerHTML = name;
      resetTimer();
    }
  }

  function playSoundStartBreak() {
    // Returns the first Element within the document
    // that matches the specified group of selectors.
    const audio = document.querySelector(`audio[data-sound="workDone"]`);
    if(!audio) return; // Stop the function from running
    audio.currentTime = 0; // Rewind to the start
    audio.play();
  }

  function playSoundBackToWork() {
    // Returns the first Element within the document
    // that matches the specified group of selectors.
    const audio = document.querySelector(`audio[data-sound="backToWork"]`);
    if(!audio) return; // Stop the function from running
    audio.currentTime = 0; // Rewind to the start
    audio.play();
  }

  function displayTimeLeft(sec) {
    const hours = parseFloat(Math.floor(sec / 3600));
    const minutes = parseFloat(Math.floor(sec / 60));
    const remainderMinutes = parseFloat(minutes % 60);
    const remainderSeconds = parseFloat(sec % 60);
    console.log(hours, remainderMinutes, remainderSeconds);

    // Play sound when timer gets to 0
    if (parseFloat(sec) === 0) {
      if (actionTypeSwitch === "Work") {
        playSoundStartBreak()
        startBreak();
      } else {
        playSoundBackToWork();
        startTimer();
      }
    }

    // Hide hours when hours is 0
    let hoursFirstStatement = hours < 10 ? "0" : "";
    let hoursSecondStatement = hours;
    let colon = ":";

    if (hours === 0) {
      hoursFirstStatement = "";
      hoursSecondStatement = "";
      colon = "";
    }

    // This `${}` allows adding javascript variables in strings
    const display = `${hoursFirstStatement}${hoursSecondStatement}${colon}${
      remainderMinutes < 10 ? "0" : ""}${remainderMinutes}:${
      remainderSeconds < 10 ? "0" : ""}${remainderSeconds}`;
    timerDisplay.textContent = display;
    document.title = display + " " + "(" + actionTypeSwitch + ")";
  }

  function displayEndTime(timestamp) {
    const end = new Date(timestamp);
    const hours = end.getHours();
    const minutes = end.getMinutes();
    endTime.textContent = `This session ends at ${hours < 10 ? "0" : ""}${hours}:${
      minutes < 10 ? "0" : ""}${minutes}`;
  }

  function changeBreakSettings() {
    const breakChangeValue = parseInt(this.dataset.settings);
    if ((breakValueSettings <= 1 && breakChangeValue === -1) ||
        (breakValueSettings >= 30 && breakChangeValue === 1))  {
      return; // Do nothing when this conditions are fulfilled
    } else {
      breakValueSettings = breakValueSettings + breakChangeValue;
      breakValue.textContent = breakValueSettings + ' min';
    }
  }

  function changeWorkSettings() {
    const workChangeValue = parseInt(this.dataset.settings);
    if ((workValueSettings <= 5 && workChangeValue === -1) ||
        (workValueSettings >= 120 && workChangeValue === 1))  {
      return; // Do nothing when this conditions are fulfilled
    } else {
      workValueSettings = workValueSettings + workChangeValue;
      workValue.textContent = workValueSettings + ' min';
    }
  }

  breakSettings.forEach(button => button.addEventListener("click", changeBreakSettings));
  workSettings.forEach(button => button.addEventListener("click", changeWorkSettings));
  buttonMain.addEventListener("click", startAndReset);
}());