似乎当我setInterval
持续1000ms时,它实际上每1001ms左右触发一次该函数。这导致时间漂移缓慢,其运行时间越长。
var start;
var f = function() {
if (!start) start = new Date().getTime();
var diff = new Date().getTime() - start;
var drift = diff % 1000;
$('<li>').text(drift + "ms").appendTo('#results');
};
setInterval(f, 1000);
运行时会立即显示不准确信息。
亲眼看看:http://jsfiddle.net/zryNf/
那么有更准确的方法来保持时间吗?或者让setInterval
表现得更准确的方法?
答案 0 :(得分:14)
我想我可能已经找到了解决方案。我想,如果你可以测量它,你可以补偿它,对吗?
var start;
var nextAt;
var f = function() {
if (!start) {
start = new Date().getTime();
nextAt = start;
}
nextAt += 1000;
var drift = (new Date().getTime() - start) % 1000;
$('<li>').text(drift + "ms").appendTo('#results');
setTimeout(f, nextAt - new Date().getTime());
};
f();
结果略有不同但这是最近的一次运行:
0ms
7ms
2ms
1ms
1ms
1ms
2ms
1ms
1ms
1ms
因此,如果它被调用1ms,2ms甚至晚10ms,那么下一次呼叫将被安排来补偿。只要每次通话都不准确,但时钟永远不会浪费时间,那么这应该可以正常工作。
现在我把它包装成一个全局accurateInterval
函数,这个函数几乎可以代替setInterval
。 https://gist.github.com/1d99b3cd81d610ac7351
答案 1 :(得分:8)
通过一些googleing,您会看到setInterval
和settimeout
都不会在您指定的确切时间执行代码。使用setInterval(f,1000);
它将在执行前等待至少1000MS,它不会等到1000MS。其他进程也在等待轮到他们使用CPU,这会导致延迟。如果你需要一个精确的计时器,时间为1秒。我会使用较短的间隔,如50MS,并将其与开始时间进行比较。我不会低于50MS,因为浏览器有最小间隔
以下是一些参考文献:
“为了理解定时器如何在内部工作,有一个需要探索的重要概念:定时器延迟无法保证。因为浏览器中的所有JavaScript都在单个线程上执行异步事件(例如鼠标点击和定时器)只有在执行中有一个开放时才会运行。最好用图表来证明,如下所示:“取自:http://css.dzone.com/news/how-javascript-timers-work
“Chrome和Chromium提供的平均时间间隔刚好超过41毫秒,第二个时钟的差异足以在一分钟内明显变慢.Safari的亮度不到41毫秒,表现优于Chrome,但仍然我在Windows XP下读取了这些读数,但Chrome在Windows 7下的表现实际上差了很多,平均时间间隔约为46毫秒。“取自: http://www.goat1000.com/2011/03/23/how-accurate-is-window.setinterval.html
答案 2 :(得分:4)
这是另一个自动校正间隔。间隔设置为较短的时间段,然后等待,直到它至少一秒钟后才能触发。它不会总是在1000毫秒之后发射(似乎在0到6毫秒的延迟范围内),但它会自动校正并且不会漂移。
修改强>
更新后使用召回setTimeout
代替setInterval
,否则在1000次左右的迭代后可能会发生奇怪的事情。
var start, tick = 0;
var f = function() {
if (!start) start = new Date().getTime();
var now = new Date().getTime();
if (now < start + tick*1000) {
setTimeout(f, 0);
} else {
tick++;
var diff = now - start;
var drift = diff % 1000;
$('<li>').text(drift + "ms").appendTo('#results');
setTimeout(f, 990);
}
};
setTimeout(f, 990);
答案 3 :(得分:1)
我看不到几乎和你的剧本一样大的漂移:
http://jsfiddle.net/hqmLg/1/
我要离开那个脚本了。现在(Chrome,Win 7)我明白了:
240.005s中的240个呼叫是0.99979个呼叫/秒
事实上,我已经看到漂移上升到.007s然后下降到.003s。我认为你的测量技术存在缺陷。
在Firefox中,我看到它漂移得更强(两个方向+/- 8ms),然后在下一次运行中进行补偿。大多数时候我在Firefox中看到“1.000000次/秒”。
答案 4 :(得分:0)
您可以使用此功能使通话保持在预期的时间表附近。它使用 Name ID_NB Rule_F
0 Alice 1715386 PDF FORMAT
3 Sarah 14881611 PDF FORMAT
4 Dee 846620760 PDF FORMAT
并根据经过的时间计算下一个通话时间。
setTimeout
答案 5 :(得分:0)
通过更改 Google Chrome 上的选项卡,可以轻松重现 setInterval 或 setTimeout 中的错误。 为了处理这些情况,您可能需要考虑为用户在另一个选项卡中的时间设置条件。
setTimeout(function() {
if (!document.hasFocus()) {
//... do something different, because more than 1 second might have passed
}
}, 1000);