每分钟呼叫功能

时间:2013-12-10 18:20:10

标签: javascript

我写的每分钟调用一个函数的代码,我认为是有缺陷的,因为它有一段时间的好处,但是自页面加载以来每小时往往会落后大约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);     

6 个答案:

答案 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);

FIDDLE

答案 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();似乎不是一个好主意。

我不会将其与以下命题进行对比,这不是必要的。

线索

  1. 使用任何必要的逻辑来计算开始时刻
  2. 开始时刻

    1. 使用setInterval执行重新执行
    2. 执行第一个电话

      • 注意 setInterval被称为ASAP,以避免时间过去。
  3. 如果您想要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);
    

    请检查both examples working on jsfiddle

    第二个(例B)似乎更准确。