JS 白痴问个倒计时的问题 - V2EX
cevincheung

JS 白痴问个倒计时的问题

  •  
  •   cevincheung Apr 18, 2016 2406 views
    This topic created in 3675 days ago, the information mentioned may be changed or developed.

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

    <!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> 
    Supplement 1    Apr 19, 2016
    已换方案,感谢指点。
    11 replies    2016-04-19 13:18:33 +08:00
    oott123
        1
    oott123  
       Apr 18, 2016 via Android
    定时器设一毫秒一次不太靠谱的,间隔实际上没那么短。
    建议你记录下开始时间,通过当前时间和开始时间的计算获取时间差,而不是每次 -1ms
    cevincheung
        2
    cevincheung  
    OP
       Apr 18, 2016
    @oott123 了解。不过还是想知道这个问题是为什么。- -# 秒数跑的好慢。复制的别人的代码稍微改了一下,别人的跑的很正常。但是我改后的秒数跑的好慢好慢。就是不知道为什么。
    oott123
        3
    oott123  
       Apr 18, 2016 via Android   1
    @cevincheung 原因没仔细想过,应该和 event loop 有关,印象中来说这个最短延迟在 4~15 ms 之间。
    你不应当依赖 setTimeout 作为准确的计时器,它可能被多方因素影响,还可能导致累积误差。
    bzw875
        4
    bzw875  
       Apr 19, 2016   1
    setTimeout 和 setInterval 是个不准时的定时器,你就记录个开始时间然后和当前时间相减吧。前面有 while(true) ;后面的定时器就不会走了,定时器有赖于进程的空闲才会执行。
    wdhwg001
        5
    wdhwg001  
       Apr 19, 2016 via iPhone   1
    事实上这玩意有个最短时间的,基于某种电池保护策略,具体每个浏览器不一样,而且好像还可以通过在页面里加动态内容使得最小时间缩短…
    但是不要在毫秒级的地方苛求 js 什么,我曾经为了毫秒级跑过无数个 jsperf ,最后发现相当一部分 best practice 是根本不存在的, ie 、 ff 和 chrome各不一样, chrome 对最佳实践优化的多一些,而 ff 和 ie 就很少出现更复杂鲁棒的用法反而性能高的诡异状况…
    YuJianrong
        6
    YuJianrong  
       Apr 19, 2016
    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
        7
    YuJianrong  
       Apr 19, 2016
    @wdhwg001 和电池保护什么的没关系请不要乱说哦~~
    顺便其实上面这个是 html5 新标准,最早的标准是说 setTimeout 都是至少 4ms ,后来改成如果是另一个 timer 的回调调用的时候(也就是可能成为递归)才至少 4ms ,最新的改成了上面这个。 Firefox 5.0 之前的版本最短时间是 10ms ( from mdn )。
    根据某人小范围的测试,至少现在的 Chrome 和 firefox 都实现了这个标准:
    https://github.com/whatwg/html/issues/239
    sunshinewu85
        8
    sunshinewu85  
       Apr 19, 2016   1
    核心原因就是: 你的递归( time-1 ) 1000 次 != 时间真正流逝 1000ms ,所以你现在的秒数实际上是程序执行递归自减 1000 次的数字而已~
    其它附带原因: @YuJianrong 说得很清楚了 :)
    doublleft
        9
    doublleft  
       Apr 19, 2016   1
    哦对, setTimeout ,第二个参数,不设置或设置过小的数字,最小为 10 ( ms )
    wdhwg001
        10
    wdhwg001  
       Apr 19, 2016 via iPhone
    @YuJianrong 好像没这么简单吧?可能会涉及到系统中断周期的问题,节能的确可能影响这个, 4ms 是确切可以达到的吗?
    YuJianrong
        11
    YuJianrong  
       Apr 19, 2016
    @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 有点希望。
    About     Help     Advertise     Blog     API     FAQ     Solana     5794 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 53ms UTC 06:44 PVG 14:44 LAX 23:44 JFK 02:44
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86