倒数计时器落后

时间:2019-01-25 11:42:57

标签: javascript

我正在尝试在2个日期之间创建倒数计时器,但是时间过了一会儿就消失了。

我的PHP后端返回当前时间与将来的X时间之间的时差,例如当前时间和提前2小时。这种差异以以下格式.countdown传递给03:20:15类的$(".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); }); 类中的HTML前端,我使用javascript函数来计算差异。这是我的功能:

span.passive.match + ul:has(span.active.match)

代码按预期工作,但几分钟后(例如2-3分钟),如果刷新页面或在新窗口中打开页面,您将看到倒数计时器落后秒数/分钟。有人知道我在做什么错吗?

1 个答案:

答案 0 :(得分:2)

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

详细信息

setInterval api规范建议应预期由于CPU负载,其他任务等导致的延迟。 https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers

您的处理程序会以大约相等的间隔被调用,而您认为它们是正确的。第一次迭代时,实际时间可能与计划时间相差很小的时间(例如4毫秒)。但是,您将计数器更改了1000 ms。随着更多次迭代的进行,这种差异不断累积并变得明显。几分钟就足以使这种情况发生。

另一方面,如果您预先计算目标日期时间值,并使用当前时间和目标时间之间的差值,则您的代码对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/