倒计时的秒数显示不正常。太慢。点解。。。
<!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?