You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pomodoro时钟Start按钮异常:多次点击致计时器加速的原因与解决

Pomodoro时钟多次点击Start按钮加速的问题解惑

我正在开发一款Pomodoro时钟,目前代码尚未完善,但发现Start按钮存在异常:单次点击可正常启动计时器,但若多次快速点击,计时器会疯狂加速。请问这是什么原因?该如何避免?


你的代码片段

HTML

<div id="title">POMODORO </div>
<div id="conteneur2">
  <div class="txt" id="damn1">Pause</div>
  <div class="txt" id="damn">Length of sessions</div>
</div>
<div id="supercont1">
  <div id="conteneur">
    <div class="el1"><input class="buto" type="button" value="-1 minute" onclick='minusOne(this)' /></div>
    <div id="output" class="el"></div>
    <div class="el1"><input class="buto" type="button" value='+1 Minute' onclick='addOne(this)' /></div>
    <div id="min1" class="el">
    </div>
    <div id="sec" class="el">
    </div>
    <div id="start"><input class="buto" type="button" id="bouton" value="START" onclick='doSomething()' /></div>
    <div class="el"><input class="buto" type="button" value='-1 Minute' onclick='minusOne1(this)' /></div>
    <div id="output2" class="el1"></div>
    <div class="el"><input class="buto" type="button" value='+1 Minute' onclick='addOne1(this)' /></div>
  </div>
</div>

CSS

#damn1 {
  padding-left: 50px;
}

#damn {
  padding-left: 450px;
}

#conteneur2 {
  display: flex;
}

.txt {
  color: #ffcf40;
  font-size: 45px;
}

.buto {
  border-radius: 50px;
  background: #ffcf40;
  text-decoration: none;
}

#output {
  font-size: 100px;
}

#output2 {
  font-size: 100px;
}

#bouton {
  height: 100px;
  width: 100px;
  margin-top: 200px;
}

#min1 {
  margin-top: 200px;
  font-size: 100px;
  color: #ffcf40;
}

#sec {
  color: #ffcf40;
  margin-top: 200px;
  font-size: 100px;
}

body {
  background: black;
}

#cont1 {
  display: flex;
  justify-content: center;
}

#conteneur {
  margin-top: 50px;
  display: flex;
  justify-content: center;
}

.el {
  width: 100px;
  height: 100px;
  color: #ffcf40;
}

.el1 {
  width: 100px;
  height: 100px;
  color: #ffcf40;
}

#title {
  margin: 0 auto;
  text-align: center;
}

JavaScript

let pause = "5";
let duree = "25";
let min = "5";
let nb = 0;
let go;
document.getElementById("output").innerHTML = pause;
document.getElementById("output2").innerHTML = duree;

function addOne(btn) {

  pause = pause + " + 1";

  console.log(pause);
  clearTimeout(go);

  document.getElementById("output").innerHTML = eval(pause);

  pause = eval(pause);
}


function minusOne(btn) {

  clearTimeout(go);
  if (eval(pause) == 0) {
    pause = pause + "";
  } else {
    pause = pause + " - 1";

  }

  document.getElementById("output").innerHTML = eval(pause);

  pause = eval(pause);
}


function addOne1(btn) {

  clearTimeout(go);

  min = min + " + 1";


  document.getElementById("output2").innerHTML = eval(min);
  document.getElementById("min1").innerHTML = eval(min) + ":";
  min = eval(min);

}

function minusOne1(btn) {

  if (eval(duree) == 0) {
    duree = duree + "";
  } else {
    min = min + " - 1";

  }

  document.getElementById("output2").innerHTML = eval(min);
  document.getElementById("min1").innerHTML = eval(min) + ":";
  clearTimeout(go);
  min = eval(min);

}

document.getElementById("min1").innerHTML = min + ":";
document.getElementById("sec").innerHTML = "  " + nb;


function doSomething() {
  if (nb > 0) {
    nb = nb - 1;
  } else if (min > 0) {
    nb = 59;
    min--;
  } else {
    min = pause
  }

  go = setTimeout(doSomething, 1000);
  document.getElementById("min1").innerHTML = min + ":";
  document.getElementById("sec").innerHTML = nb;
}

问题原因

这个问题其实很好理解:每次点击START按钮,就会调用一次doSomething()函数,而这个函数内部又会通过setTimeout(doSomething, 1000)创建一个新的定时器,让它1秒后再次执行自己。

如果多次快速点击,就会同时创建多个独立的定时器,这些定时器不会互相干扰,都会按时触发倒计时逻辑。原本每秒只执行一次的操作,现在变成每秒执行好几次,看起来计时器就疯狂加速了。

而且你的代码里虽然有clearTimeout(go),但只在调整时间的按钮里调用,点击START时并没有先清除之前可能存在的定时器,所以旧的定时器一直在运行,新的又不断叠加,自然就乱了。


解决方法

我们需要做两件核心事情:一是每次启动计时器前先清除之前的定时器,二是加个状态标记防止重复触发(避免无效的多次点击)。

修改后的JavaScript代码

let pause = 5; // 直接改成数字类型,避免使用eval
let duree = 25;
let min = 5;
let nb = 0;
let go;
let isRunning = false; // 标记计时器是否正在运行

document.getElementById("output").innerHTML = pause;
document.getElementById("output2").innerHTML = duree;

function addOne(btn) {
  clearTimeout(go);
  pause += 1; // 直接数字相加,安全又简单
  document.getElementById("output").innerHTML = pause;
}

function minusOne(btn) {
  clearTimeout(go);
  if (pause > 0) {
    pause -= 1;
  }
  document.getElementById("output").innerHTML = pause;
}

function addOne1(btn) {
  clearTimeout(go);
  min += 1;
  document.getElementById("output2").innerHTML = min;
  document.getElementById("min1").innerHTML = min + ":";
}

function minusOne1(btn) {
  clearTimeout(go);
  if (min > 0) {
    min -= 1;
  }
  document.getElementById("output2").innerHTML = min;
  document.getElementById("min1").innerHTML = min + ":";
}

document.getElementById("min1").innerHTML = min + ":";
document.getElementById("sec").innerHTML = "  " + nb;

// 新增专门的启动函数,代替直接调用doSomething
function startTimer() {
  if (isRunning) return; // 如果已经在运行,直接返回,不重复启动
  isRunning = true;
  clearTimeout(go); // 先清除之前的定时器,确保只有一个在运行
  doSomething();
}

function doSomething() {
  if (nb > 0) {
    nb -= 1;
  } else if (min > 0) {
    nb = 59;
    min -= 1;
  } else {
    min = pause;
    // 这里可以添加休息时间的提示逻辑
  }

  document.getElementById("min1").innerHTML = min + ":";
  document.getElementById("sec").innerHTML = nb;

  go = setTimeout(doSomething, 1000);
}

修改HTML中的START按钮

把原来的onclick='doSomething()'改成onclick='startTimer()':

<div id="start"><input class="buto" type="button" id="bouton" value="START" onclick='startTimer()' /></div>

额外小建议

  • 我把所有eval()都去掉了,因为它不仅性能差,还存在安全风险,直接把变量定义成数字类型,加减操作更简单安全。
  • 你还可以添加一个暂停按钮,点击时执行clearTimeout(go)并把isRunning设为false,让计时器功能更完整。

内容的提问来源于stack exchange,提问作者Jukker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:26:32