JS 白痴问个倒计时的问题

2016-04-18 22:35:01 +08:00
 cevincheung

倒计时的秒数显示不正常。太慢。点解。。。 ??

<!DOCTYPE html>
<html>
  
  <head>
    <meta charset="UTF-8">
  </head>
  
  <body>
      
    <h2>毫秒的倒计时</h2>
    <div id="timer2"></div>
    <script>
      var countdown = function(gid,time){
        try {
            if (time<=0) {
            } else {

                var ms = Math.floor(time%1000);
                var s = Math.floor(time/1000%60);
                var m = Math.floor(time/1000/60%60);
                var h =Math.floor(time/1000/60/60%24);

                h=h>9?h:'0'+h;
                m=m>9?m:'0'+m;
                s=s>9?s:'0'+s;
                ms=ms>9?ms:'0'+ms;
                if (parseInt(h)>0) {
                    var str = h+':'+m+':'+s;
                } else {
                    var str = m+':'+s+':'+ms;
                }
                document.getElementById('timer2').innerHTML = str;
                setTimeout(function(){
                    countdown(gid,time-1);
                },1);
            }
        } catch (e) {
            if (typeof(console) == 'object') {
                console.log(e);
            }
        }
    };
    setTimeout(function(){countdown('timer2',99999)},1);
  
    </script>
      
      </body>
</html>
1767 次点击
所在节点    问与答
11 条回复
oott123
2016-04-18 22:39:49 +08:00
定时器设一毫秒一次不太靠谱的,间隔实际上没那么短。
建议你记录下开始时间,通过当前时间和开始时间的计算获取时间差,而不是每次 -1ms
cevincheung
2016-04-18 22:43:27 +08:00
@oott123 了解。不过还是想知道这个问题是为什么。- -# 秒数跑的好慢。复制的别人的代码稍微改了一下,别人的跑的很正常。但是我改后的秒数跑的好慢好慢。就是不知道为什么。
oott123
2016-04-18 23:50:37 +08:00
@cevincheung 原因没仔细想过,应该和 event loop 有关,印象中来说这个最短延迟在 4~15 ms 之间。
你不应当依赖 setTimeout 作为准确的计时器,它可能被多方因素影响,还可能导致累积误差。
bzw875
2016-04-19 00:20:38 +08:00
setTimeout 和 setInterval 是个不准时的定时器,你就记录个开始时间然后和当前时间相减吧。前面有 while(true) ;后面的定时器就不会走了,定时器有赖于进程的空闲才会执行。
wdhwg001
2016-04-19 00:42:29 +08:00
事实上这玩意有个最短时间的,基于某种电池保护策略,具体每个浏览器不一样,而且好像还可以通过在页面里加动态内容使得最小时间缩短…
但是不要在毫秒级的地方苛求 js 什么,我曾经为了毫秒级跑过无数个 jsperf ,最后发现相当一部分 best practice 是根本不存在的, ie 、 ff 和 chrome 各不一样, chrome 对最佳实践优化的多一些,而 ff 和 ie 就很少出现更复杂鲁棒的用法反而性能高的诡异状况…
YuJianrong
2016-04-19 01:00:38 +08:00
setTimeout 时间延迟比较长的原因很简单……因为标准就是这样的……

https://html.spec.whatwg.org/multipage/webappapis.html#timers

8. If nesting level is greater than 5, and timeout is less than 4, then increase timeout to 4.

nesting level 是指这个 timer 是被另一个 timer 回调函数递归调用的深度,前 4 个递归的 timeout 按原时间调用,第 5 个开始延时会增加到至少 4ms

当然,除了这个因素之外,还有你的各种处理也会消耗时间;回调也是在 JS 线程开始运转,消息队列在 timer 之前跑完才跑,所以间隔当然不只是设置的那点时间了。

不用说正确方法当然是取时间来处理。
YuJianrong
2016-04-19 01:10:14 +08:00
@wdhwg001 和电池保护什么的没关系请不要乱说哦~~
顺便其实上面这个是 html5 新标准,最早的标准是说 setTimeout 都是至少 4ms ,后来改成如果是另一个 timer 的回调调用的时候(也就是可能成为递归)才至少 4ms ,最新的改成了上面这个。 Firefox 5.0 之前的版本最短时间是 10ms ( from mdn )。
根据某人小范围的测试,至少现在的 Chrome 和 firefox 都实现了这个标准:
https://github.com/whatwg/html/issues/239
sunshinewu85
2016-04-19 03:20:16 +08:00
核心原因就是: 你的递归( time-1 ) 1000 次 != 时间真正流逝 1000ms ,所以你现在的秒数实际上是程序执行递归自减 1000 次的数字而已~
其它附带原因: @YuJianrong 说得很清楚了 :)
doublleft
2016-04-19 10:04:12 +08:00
哦对, setTimeout ,第二个参数,不设置或设置过小的数字,最小为 10 ( ms )
wdhwg001
2016-04-19 12:41:46 +08:00
@YuJianrong 好像没这么简单吧?可能会涉及到系统中断周期的问题,节能的确可能影响这个, 4ms 是确切可以达到的吗?
YuJianrong
2016-04-19 13:18:33 +08:00
@wdhwg001 1. 我只谈标准,标准就这么定的,原因什么的其实真无所谓(要谈一下的话其实原因也很简单, HTML 的标准一般来说都是事实标准——因为最早的 setTimeout 实现为了防止 setTimeout(0)造成浏览器锁死,所以故意延迟了时间,之后 chrome 曾试图移除 setTimeout 最小时间限制,结果有些网站就完蛋了,所以后来干脆写进标准)。
2. ms 级精度对现在的系统来说真是小菜一碟,不会有什么系统啦中断啦的原因。连 HTML5 的高精度计时器标准都达到了微秒级精度: https://developer.mozilla.org/en-US/docs/Web/API/Performance/now
3. 节能是不是影响不知道(看浏览器实现吧,比如 Firefox 对于在后台 tab 的 timer 就至少 1000ms 才跑一次),反正标准没写……

当然介于消息队列实现原理, nested 的 setTimeout(4ms)是肯定不能确切 4ms 运行的, setInterval 有点希望。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/272099

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX