首页 > 关于JS倒计时的问题

关于JS倒计时的问题

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


<!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>

在线测试:https://jsfiddle.net/L6qvefu3/


这个应该算是它的一个不准确性吧,setTimeout作为倒计时,准确性会有一定性的影响,尤其是倒计时间隔为10ms以下的时候更为明显,不同浏览器对于这个函数的最小执行间隔会有不同的设定,但通常不会低于5ms,即使你设置为0ms,也不会立即去执行!因为它有一个最小间隔!
同理,你设置的1ms执行也会产生这个问题!

setTimeout 和 setInterval 经常被用来做网页上的定时器,允许为它指定一个毫秒数作为间隔执行的时间。当被启动的程序需要在非常短的时间内运行,我们就会给她指定一个很小的时间数,或者需要马上执行的话,我们甚至把这个毫秒数设置为0,但事实上,setTimeout有一个最小执行时间,当指定的时间小于该时间时,浏览器会用最小允许的时间作为setTimeout的时间间隔,也就是说即使我们把setTimeout的毫秒数设置为0,被调用的程序也没有马上启动。

这个最小的时间间隔是多少呢?这和浏览器及操作系统有关。在John Resig的新书《Javascript忍者的秘密》一书中提到

Browsers all have a 10ms minimum delay on OSX and a(approximately) 15ms delay on Windows.(在苹果机上的最小时间间隔是10毫秒,在Windows系统上的最小时间间隔大约是15毫秒) 

,另外,MDC中关于setTimeout的介绍中也提到,Firefox中定义的最小时间间隔(DOM_MIN_TIMEOUT_VALUE)是10毫秒,HTML5定义的最小时间间隔是4毫秒。既然规范都是这样写的,那看来使用setTimeout是没办法再把这个最小时间间隔缩短了。

最后,建议你去使用更加准确的setInterval来倒计时吧!


javascript的setTimeout的作用是每隔一段时间把指定函数放到任务队列里,排队执行。并不能保证马上执行。
你的

setTimeout(function(){countdown('timer2',99999)},1);

意思是每隔1毫秒把countdown函数放到任务队列里,等待cpu顺序执行。

所以,你希望cpu在1000毫秒内能够执行1000次countdown函数,实际上只是这1000毫秒内setTimeout函数把1000个countdown函数放到任务队列里去而已,实际上cpu执行完这1000个countdown函数的时间肯定会大于1000毫秒。

javascript只能初略计算时间。如果要做一个精确计时的话还是利用时间戳

var date = new Date()
date.getTime(); //从1970.1.1开始的毫秒数

这个来显示时间吧。


@Hello_World20 说的就是正确的,js里要准确计时只能用Date的时间戳
按题主的代码改了下,应该就是题主想要的效果了

<!DOCTYPE html>
<html>
  
  <head>
    <meta charset="UTF-8">
  </head>
  
  <body>
      
    <h2>毫秒的倒计时</h2>
    <div id="timer2"></div>
    <script>
      var countdown = function(gid,time,starttime){
        if (!starttime) starttime = Date.now();
        try {
            var _time = time + starttime - Date.now();
            if (_time<=0) {
                document.getElementById('timer2').innerHTML = '00:00:00';
            } 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, starttime);
                },1);
            }
        } catch (e) {
            if (typeof(console) == 'object') {
                console.log(e);
            }
        }
    };
    setTimeout(function(){countdown('timer2',99999)},1);
  
    </script>
      
      </body>
</html>

setTimeout还要递归调用,为什么不直接用setInterval?

【热门文章】
【热门文章】