0

在我们的应用程序中,我们需要一个强大的倒数计时器。当计时器倒计时到零时,我们将用户移至下一页。

这里有很多关于在 JavaScript 中制作倒数计时器的问题。我已经筛选了很多,查看了很多代码示例,尝试了很多插件,但对于这个测试案例,所有这些都失败了:如果你调整你的计算机系统时钟,所有这些计时器都会搞砸(获得时间,失去时间,或者只是冻结)。原因是他们中的大多数基于他们的逻辑保存一些初始开始时间,然后在某个时间间隔(通过 setTimeout 或 setInterval)获取当前时间并在它和开始时间之间进行差异。当您调整系统时间时,“当前”时间可以是开始时间前一小时或几天,也可能是几小时或几天后。

因此,我想出了以下代码来尝试处理这些系统更改场景。我做的主要事情是检查我的开始和当前之间的“差异”是否为负(或大于大约一小时来处理自动夏令时调整),以仅使用滴答间隔作为近似值。此外,在每个刻度上将开始时间重置为当前时间,以便经过时间是差异之间时间的总和,而不仅仅是初始开始时间和当前时间之间的差异。有人看到这种方法有任何缺陷吗?

var timeLeft = 60000, // time left in ms, 1 minute for this example
    startTime, 
    totalElapsedTime = 0,
    TICK_INTERVAL = 500; // the setTimeout interval


var timerTick = function () {

    var now = new Date(),
        elapsedTime = now.getTime() - startTime.getTime();

    // if the elapsed time was positive and less than approximately an hour, then add the elapsed time to the total
    // otherwise, add the TICK_INTERVAL, which we know is the theoretical minimum between timerTick() calls

    totalElapsedTime = (elapsedTime > 0 && elapsedTime < 3590000) ? totalElapsedTime + elapsedTime : totalElapsedTime + TICK_INTERVAL;

    // reset start time 
    startTime = now;

    // there is time left, so set up another tick
    if (totalElapsedTime < timeLeft) {

        // update the html that is displaying remaining time

        setTimeout(timerTick, TICK_INTERVAL);          

    }
    else {

        // time ran out, so do whatever you do when it runs out            

    }
}


// start the timer
startTime = new Date();
setTimeout(timerTick, TICK_INTERVAL);
4

1 回答 1

1

为什么以下内容对您不起作用?

var timeleft = 60000,
    tick = 1000,
    intervalID = window.setInterval(function () {
        timeleft = timeleft - tick;
        if (timeleft <= 0) {
            // clear the interval
            clearInterval(intervalID);

            // do something
        }
    }, tick);

更新

使用setTimeout(这会漂移,但除非您将其用于动画,否则可能没问题):

var timeleft = 60000,
    tick = 1000;

window.setTimeout(function timerFn() {
    timeleft = timeleft - tick;
    if (timeleft > 0) {
        // set the next timeout
        setTimeout(timerFn, tick);
    } else {
        // do something
    }
}, tick);
于 2012-11-21T18:52:12.103 回答