我写的每分钟调用一个函数的代码,我认为是有缺陷的,因为它有一段时间的好处,但是自页面加载以来每小时往往会落后大约15秒。说实话,我无法弄清楚导致滞后的原因,也许是执行功能所需的时间,小的失误都会累积和累积。有没有办法自动纠正函数内的失误。或者也许有人知道在分钟函数调用上实现更好的方法。任何帮助或想法非常感谢。感谢。
var now = new Date();
var delay = 60 * 1000; // 1 min in msec
var start = delay - (now.getSeconds()) * 1000 + now.getMilliseconds();
setTimeout(function setTimer() {
onTheMinFunc();
setTimeout(setTimer, delay);
}, start);
答案 0 :(得分:5)
首先,DOM Timers API不保证准确性。 I quote:
此API不保证计时器将按计划运行。由于CPU负载,其他任务等原因导致延迟。
其次,由于执行onTheMinFunc()
的时间导致每轮的延迟(你只在完成时设置超时)。
所以,让我们说onTheMinFunc
需要半秒才能执行 - 你每分钟都会得到半秒钟的延迟而且会累积 - 只需要10分钟就会延迟一段时间。 (注意,函数通常不应超过15ms才能执行以避免明显滞后)
尝试:
setInterval(onTheMinFunc, delay);
它仍然不会很准确。您可以在更短的时间间隔内进行轮询,并跟踪日期变量 - 但同样 - 不能保证。
答案 1 :(得分:3)
您可能想要的是setInterval
:
setInterval(onTheMinFunc, delay);
原样,使用setTimeout
的代码意味着执行onTheMinFunc
所需的时间会在下一个启动之前添加到您的延迟中,所以随着时间的推移,这个额外的延迟会增加起来。
使用setInterval
会更准确,因为延迟是在执行函数的调用之间,而不是仅在函数完成后启动计时器。
答案 2 :(得分:1)
定时器和javascript时间不是很准确,我认为确保函数每隔一分钟执行一次的唯一方法就是每秒检查秒数
setInterval(function() {
if ( new Date().getSeconds() === 0 ) onTheMinFunc();
},1000);
答案 3 :(得分:1)
我想你想要更接近这个:
function setNextMinute() {
// figure out how much time remains before the end of the current minute
var d = new Date().getTime()%60000;
//set a timeout to occur when that expires.
setTimeout(function () {
// recalculate a new timeout so that your timer doesn't lag over time.
doWhateverYouWantToHere();
// note that calling doWhateverYouWantToHere() will
// not offset the next minute, since it is recalculated in setNextMinute()
setNextMinute();
},60000-d);
}
setNextMinute();
警告:我没有彻底测试这个时间。但它看起来间隔1秒,间隔1分钟就足够了。
这样做的好处是不会每秒重新计算,也不仅仅是从当前时间开始计时60秒。
答案 4 :(得分:1)
以下是对您的代码的轻微修改:
function everyMinute(fn) {
arguments[1] && fn();
var now = new Date();
var delay = 60 * 1000 - (now.getSeconds()) * 1000 + now.getMilliseconds();
setTimeout(function(){
everyMinute(fn, true);
}, start);
}
everyMinute(onTheMinFunc);
它会重新计算每次等到下一分钟的毫秒数,以便尽可能准确地达到分钟的最高点。
答案 5 :(得分:0)
每秒(并且永远)执行if ( new Date().getSeconds() === 0 ) onTheMinFunc();
似乎不是一个好主意。
我不会将其与以下命题进行对比,这不是必要的。
在开始时刻
setInterval
执行重新执行执行第一个电话
setInterval
被称为ASAP,以避免时间过去。new Date().getSeconds() === 0
:var id = setInterval(function() {
if ( new Date().getSeconds() === 0 ) {
setInterval(onTheMinFunc, delay);
onTheMinFunc();
clearInterval(id);
}
},1000);
var now = new Date();
var delay = 60 * 1000; // 1 min in msec
var start = delay - (now.getSeconds()) * 1000 + now.getMilliseconds();
setTimeout(function() {
setInterval(onTheMinFunc, delay);
onTheMinFunc();
}, start);
第二个(例B)似乎更准确。