选项卡处于非活动状态时,Javascript setInterval无法正常工作

时间:2015-06-16 15:39:35

标签: javascript jquery setinterval

function initTimer(timeLeft) {
     var Me = this,
     TotalSeconds = 35,
     Seconds = Math.floor(timeLeft);

     var x = window.setInterval(function() {
         var timer = Seconds;

         if(timer === -1) { clearInterval(x); return; }

            $('#div').html('00:' + (timer < 10 ? '0' + timer : timer));
            Seconds--;

         },1000);
     }

我有这个代码。一切正常,当此选项卡在浏览器中处于活动状态时,但是当我更改选项卡并稍后在选项卡中返回时,它会出现问题。更准确地说,它错误地显示时间。

我也试过了setTimeout,但问题是一样的。

我的一个想法是:HTML5 Web Workers ......

但这是另一个问题......浏览器支持。

有人可以帮助解决这个问题吗? 如何编写setInterval,即使tab不活动也能正常工作

2 个答案:

答案 0 :(得分:2)

使用Date对象计算时间。当你问它时,不要依赖计时器触发(它们不是实时的),因为你唯一的保证就是在你要求它之前不会发射。它可能会在很晚的时候激活,尤其是对于非活动选项卡。尝试这样的事情:

function  initTimer(periodInSeconds) {
            var end = Date.now() + periodInSeconds * 1000;


            var x = window.setInterval(function() {
                var timeLeft = Math.floor((end - Date.now()) / 1000);

                if(timeLeft < 0) { clearInterval(x); return; }

                $('#div').html('00:' + (timeLeft < 10 ? '0' + timeLeft : timeLeft));
            },200);
        }

initTimer(10);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div"></div>

请注意,通过更频繁地检查它,我们可以确保它永远不会过多。

答案 1 :(得分:1)

即使标签处于有效状态,JavaScript定时器也不可靠。他们只保证至少你指定的时间已经过去了;无法保证完全那段时间,甚至是接近它的任何时间都已过去。

要解决此问题,每当间隔触发时,请注意它的时间。您实际上只需要跟踪两次:当前时间和上一个间隔触发的时间。通过从当前刻度的时间减去前一个刻度的时间,您可以知道实际在两者之间传递了多少时间,并相应地运行计算。

以下是这样的事情的基本概要:

function  initTimer(timeLeft) {
        var Me           = this,
            TotalSeconds = 35,
            Seconds      = Math.floor(timeLeft),
            CurrentTime  = Date.now(),
            PreviousTime = null;

        var x = window.setInterval(function() {
            var timer = Seconds,
                timePassed;
            PreviousTime = CurrentTime;
            CurrentTime = Date.now();
            timePassed = CurrentTime - PreviousTime;

            if(timer < 0) { clearInterval(x); return; }

            $('#div').html('00:' + (timer < 10 ? '0' + timer : timer));
            Seconds = Seconds - timePassed;

        },1000);
    }