防止 JS 定时器溢出

Preventing overflow in JS Timer

我根据 this 问题的投票最多的答案做了一个计时器。 问题是,当它达到 0 时,它会将日期更改为第二天并启动一个新的 24 小时计时器。

Tl;博士 00:00:00 -> 23:59:59 而不是永远保持 00:00:00。

我当前的代码:

function getTimeLeft() {
  var seconds_left = end_time - Math.floor(Date.now() / 1000);
  var time_left = new Date(seconds_left * 1000).toISOString().substr(11, 8);
  $('#test-time-left').text(time_left);
}
setInterval(getTimeLeft, 1000);

为了保持00:00:00,我想到了2种解决方法

首先(恕我直言)会在条件为 seconds_left >= 0while 循环中给出 setInterval(getTimeLeft, 1000);。但我对此没有什么问题。

  1. 我不知道如何在函数外传递变量。

  2. 我不知道阻止 setInterval 是否会有任何作用,但我最好将间隔设置为 0(因此将其关闭)。

第二种方法是简单地在函数内部执行 while:

while( seconds_left >= 0){
      var time_left = new Date(seconds_left * 1000).toISOString().substr(11, 8);
}

问题:

  1. 浪费资源,因为JS脚本还在做

@编辑最终结果:

function getTimeLeft() {
  var seconds_left = end_time - Math.floor(Date.now() / 1000);
  if (seconds_left <= 0)
  {
    seconds_left = 0;
    clearInterval(timer);
  }
  var time_left = new Date(seconds_left * 1000).toISOString().substr(11, 8);
  $('#test-time-left').text(time_left);
}
var timer = setInterval(getTimeLeft, 1000);

我还将 seconds_left 设置为 0,以防脚本错过 0 秒帧(例如用户在倒计时发生时关闭浏览器)。

假设您想在 seconds_left 等于 0 时停止计时器,您可以简单地清除间隔:

function getTimeLeft() {
  var seconds_left = end_time - Math.floor(Date.now() / 1000);
  var time_left = new Date(seconds_left * 1000).toISOString().substr(11, 8);
  if(seconds_left === 0) {
    clearInterval(timer);  // clear the interval
  }
  $('#test-time-left').text(time_left);
}

var timer = setInterval(getTimeLeft, 1000);  //save the timer in a variable

请注意,您使用 while 循环的想法不会起作用:

while( seconds_left >= 0){
  var time_left = new Date(seconds_left * 1000).toISOString().substr(11, 8);
}

JavaScript 是 single-threaded,这意味着间隔代码将 而不是 运行 而你的 while 循环是运行ning,因此创建一个无限循环(并可能使您的浏览器崩溃)。

我同意 Rick Hithcock 所说的一切。这是一个基于您的代码的示例,该示例将计时器设置为从现在起 10 秒,然后倒计时。

var end_time = new Date();
end_time.setSeconds(end_time.getSeconds() + 10);

function getTimeLeft() {
    var now = new Date();
    var seconds_left = (end_time - now) / 1000;
    if (seconds_left <= 1) {
        clearInterval(timerID);
    }
    var time_left = new Date(seconds_left * 1000).toISOString().substr(11, 8);
    $('#test-time-left').text(time_left);
}
timerID = setInterval(getTimeLeft, 1000);