最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

jquery - Javascript setInterval doesn't work correctly when tab is not active - Stack Overflow

programmeradmin0浏览0评论
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);
     }

I have this code. Everything works fine, when this tab is active in browser, but when I change tab and return in tab later it has problems. To be more precise, it Incorrectly displays the time.

I'd also tried setTimeout, but problem was the same.

One idea, which I have is: HTML5 Web Workers...

But here is another problem... browsers support.

can someone help to solve this problem? How can I write setInterval, which works properly,even when tab is not active

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);
     }

I have this code. Everything works fine, when this tab is active in browser, but when I change tab and return in tab later it has problems. To be more precise, it Incorrectly displays the time.

I'd also tried setTimeout, but problem was the same.

One idea, which I have is: HTML5 Web Workers...

But here is another problem... browsers support.

can someone help to solve this problem? How can I write setInterval, which works properly,even when tab is not active

Share Improve this question edited Jun 16, 2015 at 16:24 TaoPR 6,0523 gold badges27 silver badges38 bronze badges asked Jun 16, 2015 at 15:39 zarandaaazarandaaa 511 gold badge2 silver badges5 bronze badges 6
  • What browser have you tried? – TaoPR Commented Jun 16, 2015 at 15:42
  • 2 Browsers can and do throttle calls to setInterval callbacks when the tabs are not active. You need to take this into account when designing your code. – James Thorpe Commented Jun 16, 2015 at 15:43
  • 3 timers are NOT real-time. If you ask a timer to fire every 1 second then all it guarantees you is that it won't fire sooner than 1 second. It could be a lot later (especially if the tab is inactive). If you want to accurately measure time then record the time when you start the timer and then on each tick calculate the elapsed time with Date.now() – Matt Burland Commented Jun 16, 2015 at 15:44
  • 2 Further to my point - even if the tab is active, setInterval only guarantees a minimum time until your code is called. If you're doing time based calculations, you're better off keeping hold of the "starting time" and doing further calculations based off that, rather than incrementing/decrementing a variable. – James Thorpe Commented Jun 16, 2015 at 15:45
  • 1 @MattBurland I see you furthered my point already :) – James Thorpe Commented Jun 16, 2015 at 15:45
 |  Show 1 more ment

2 Answers 2

Reset to default 9

Use the Date object to calculate time. Don't rely on a timer firing when you ask it to (they are NOT real-time) because your only guarantee is that it'll not fire before you ask it to. It could fire much later, especially for an inactive tab. Try something like this:

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./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div"></div>

Note that by checking it more frequently we can make sure it's never off by too much.

JavaScript timers are not reliable, even when the tab is active. They only guarantee that at least as much time as you specified has passed; there is no guarantee that exactly that amount of time, or even anything close to it, has passed.

To solve this, whenever the interval fires, note what time it is. You really only need to keep track of two times: the current time, and the time that the previous interval fired. By subtracting the previous tick's time from the current tick's time, you can know how much time has actually passed between the two, and run your calculations accordingly.

Here's a basic outline of how something like this might look:

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);
    }
发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>