请注意:链接到问题不回答我的问题。 Bergi的答案是我所要求的正确答案。
首先,请看一下这个简单的CountdownTimer:
http://jsfiddle.net/49tH7/(请参阅下面的永久性代码)
确保打开控制台,以便您可以看到倒计时。我使用最新版本的chrome进行了测试。
请注意我们调用计时器的方式:
timer = CountdownTimer(5000, 5, function(tickNum) { console.log(tickNum) });
timer.start();
我们传递计时器应该采取的总时间倒计时(5000毫秒),它应该完成的滴答总数(在这种情况下每秒5 - 1),以及在每个滴答时调用的回调函数。回调传递了tick的编号,在这种情况下它只是打印出来。代码执行完毕后,将调用onFinish()
方法,该方法只打印出计时器刚刚运行的总ms数。理论上,这应该总是非常接近传递给CountdownTimer
构造函数的第一个参数,在本例中为5000。
ticks之间的时间是自适应的,考虑到执行回调所花费的时间。如果回调代码平均缓慢且复杂,optimalPauseTime()
方法将检测到这一点,并开始调整滴答之间的时间,以便计时器仍然在{{1}的第一个参数中指定的总时间内完成}。因此,计时器的总运行时间和刻度总数是固定量,但刻度之间的时间是动态的和可变的。
要看到激发这篇文章的陌生感,请将小提琴中的刻度数增加到1000并打破手机的秒表:
CountdownTimer
按下跑步后立即启动秒表,并在看到控制台输出结束后立即停止。显然这是一个粗略的估计,可能会被一秒钟关闭,但它足以看到正在发生的事情。日志的最终输出如下所示:
timer = CountdownTimer(5000, 1000, function(tickNum) { console.log(tickNum) });
timer.start();
我的秒表读取8.5秒。我做了多次测试,结果相似。
问题1 javascript代码如何声称它只需要5004毫秒才能运行,而实际需要花费几秒钟的时间?
问题2 要查看问题的夸张版本并观察CPU的拍摄,请将滴答声调高至2000并再次运行。在这种情况下,我的秒表运行大约需要25秒,最终的数字输出是8727.所以现在代码能够检测到它的运行速度更慢,但它仍然低估了这么慢的速度。这是怎么解释的呢?
999 (index):54
1000 (index):54
5004
答案 0 :(得分:2)
如果javascript代码声称它只需要5004毫秒才能运行,那么它实际上需要花费几秒钟的时间才能运行吗?
我无法重现。也许你的秒表(或触发它的过程?)是不准确的; new Date
通常效果很好。
也许您也只是遇到控制台延迟,它不会经常更新以顺利运行页面。在控制台中显示大量消息可能是瓶颈(不应将它们写入控制台缓冲区)。
要查看问题的夸张版本并观察CPU的拍摄,请将嘀嗒声调高至2000并再次运行。在这种情况下,我的秒表运行大约需要25秒,最终的数字输出是8727.所以现在代码能够检测到它的运行速度更慢,但它仍然低估了这么慢的速度。这是怎么解释的呢?
浏览器中实现了最小超时。在5s内有2000个滴答,预计每2.5ms会有一个滴答,这太低了。浏览器无法快速安排滴答。
此外,onFinish()
调用总是被推迟一次,即通常在实际结束后大约4ms。
此外,您的optimalPauseTime
并非旨在确切,而是为了平等分配超时。当它迟到并试图赶上时,它并没有立即赶上 - 而是将这个追赶分布在剩余的蜱上。相反,你可能会做类似
function tick() {
ticksCompleted++;
tickCb(ticksCompleted);
if (ticksCompleted == totalTicks) {
onFinish();
} else {
var pause = optimalPauseTime();
if (pause <= 0)
tick();
else
setTimeout(tick, pause);
}
}
function optimalPauseTime() {
var timeElapsed = new Date() - startTime;
var nextTickRatio = (ticksCompleted + 1) / totalTicks;
var expectedNextTime = totalMs * nextTickRatio;
return expectedNextTime - timeElapsed;
}