javascript - 倒计时计时器滞后

标签 javascript

我正在尝试在 2 个日期之间创建倒数计时器,但一段时间后时间就滞后了。

我的 PHP 后端返回当前时间和 future X 时间之间的差异,例如当前时间和提前 2 小时。此差异以以下格式传递到 .countdown 类中的 HTML 前端 03:20:15 我使用 javascript 函数对差异进行倒计时。这是我的功能:

$(".countdown").each(function() {
   var $e = $(this);
   var interval = setInterval(function() { 
      var timer2 = $e.html();
      var timer = timer2.split(':');
      var hours = parseInt(timer[0], 10);
      var minutes = parseInt(timer[1], 10);
      var seconds = parseInt(timer[2], 10);
      --seconds;
      minutes = (seconds < 0) ? --minutes : minutes;
      hours = (minutes < 0) ? --hours : hours;
      if(hours < 0) {
         clearInterval(interval);
         window.location.reload();
      } else {
         seconds = (seconds < 0) ? 59 : seconds;
         seconds = (seconds < 10) ? '0' + seconds : seconds;
         minutes = (minutes < 0) ? 59 : minutes;
         minutes = (minutes < 10) ? '0' + minutes : minutes;
         hours = (hours < 10) ? '0' + hours : hours;
         $e.html(hours + ':' + minutes + ':' + seconds);
      }
   }, 1000);
});

代码按预期运行,但几分钟后,比方说 2-3 分钟,如果您刷新页面或在新窗口中打开它,您将看到倒计时计时器滞后了秒/分钟。有人知道我做错了什么吗?

最佳答案

您应该计算 (new Date()) 和目标日期之间的差异。使用该差异并格式化新的 HTML 字符串,而不是将其解析为小时、分钟、秒值以进行递减。

详情

setInterval api 规范表明,由于 CPU 负载、其他任务等导致的延迟是可以预料的。 https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers

当您认为它们是准确的时,您的处理程序会以大致相等的间隔被调用。在第一次迭代中,实际时间可能与计划时间有一定差异(比如 4 毫秒)。然而,您正在将计数器更改 1000 毫秒。随着更多的迭代通过,这种差异会累积并变得明显。几分钟就足以让这一切发生。

另一方面,如果您预先计算目标日期时间值并将使用当前时间和目标时间之间的差异,您的代码将不会对 api 的不精确性敏感。

$(".countdown").each(function () {
    var $e = $(this);

    const totalSeconds = (dt) => Math.floor(dt.valueOf() / 1000);

    const f1 = (timer2) => {
        var timer = timer2.split(':');
        var tdt = new Date().setHours(
            parseInt(timer[0]) + tdt.getHours(),
            parseInt(timer[1]) + tdt.getMinutes(),
            parseInt(timer[2]) + tdt.getSeconds());
        return totalSeconds(tdt);
    };

    const targetTime = f1($e.html());

    setInterval(function () {
        var timeSpan = targetTime - totalSeconds(new Date());

        if (timeSpan < 0) {
            window.location.reload();
        } else {
            var seconds = timeSpan % 60;
            var totalMinutes = Math.floor(timeSpan / 60);
            var minutes = totalMinutes % 60;
            var hours = Math.floor(totalMinutes / 60);

            $e.html(hours + ':' + minutes + ':' + seconds);;
        }
    }, 1000);
});

另见: https://jsfiddle.net/8dygbo9a/1/

关于javascript - 倒计时计时器滞后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54364671/

相关文章:

javascript - 在 MongoDB 和 Mongoose 中执行全文搜索的最佳方法

javascript - jsdoc 记录 socket.on ('event' , function() {}) 和路由处理程序的正确方法

javascript - 关于node.js/javascript在文件之间共享变量

php - 同时选择+文本输入表单字段?

javascript - 在 React 中将每个 api 响应存储在数组中

javascript - Fabric.js 拖动事件不起作用

javascript - 'If' -'else' jQuery 函数中的语句

javascript - Google CryptoJS AES 结果太长 1 个区 block

javascript - 如何在 javascript 单元测试期间加载二进制文件?

javascript - 未处理的 promise 拒绝警告 : Error: The client is closed in NodeJS and Redis