简体   繁体   English

每分钟呼叫功能

[英]call function on the minute every minute

The code I wrote to call a function on the minute every minute, I think is flawed, as It's good for a while, but tends to lag behind by about 15 seconds for every hour since the page was loaded. 我写的每分钟调用一个函数的代码,我认为是有缺陷的,因为它有一段时间的好处,但是自页面加载以来每小时往往会落后大约15秒。 To be honest I can't figure out what's causing the lagging, maybe it's the time it takes the functions to execute, small lapses all adding up and accumulating. 说实话,我无法弄清楚导致滞后的原因,也许是执行功能所需的时间,小的失误都会累积和累积。 Is there a way to auto-correct the lapses within the function as it's called. 有没有办法自动纠正函数内的失误。 Or maybe someone knows a better method of achieving on the minute function calls. 或者也许有人知道在分钟函数调用上实现更好的方法。 Any help or ideas much appreciated. 任何帮助或想法非常感谢。 Thanks. 谢谢。

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

First of all, the DOM Timers API does not guarantee accuracy. 首先,DOM Timers API不保证准确性。 I quote : 我引述

This API does not guarantee that timers will run exactly on schedule. 此API不保证计时器将按计划运行。 Delays due to CPU load, other tasks, etc, are to be expected. 由于CPU负载,其他任务等导致的延迟是预期的。

Second, you have a lag on each round caused by the time onTheMinFunc() is executed (you only set the timeout when it's done). 其次,你执行onTheMinFunc()会导致每一轮延迟(你只在完成时设置超时)。

So, let's say onTheMinFunc takes half a second to execute - you get half a second delay at each minute and it accumulates - after only 10 minutes it'll lag quite a bit. 所以,让我们说onTheMinFunc需要半秒才能执行 - 你每分钟都会得到半秒钟的延迟并且它会累积 - 只需要10分钟它就会相当滞后。 (Note, functions should usually not take more than 15ms to execute anyway to avoid noticeable lag) (注意,函数通常不应超过15ms才能执行以避免明显滞后)

Try: 尝试:

setInterval(onTheMinFunc, delay);

It still won't be very accurate. 它仍然不会很准确。 You can poll on much shorter intervals and keep track of a date variable - but again - no guarantees. 您可以在更短的时间间隔内轮询并跟踪日期变量 - 但同样 - 无法保证。

What you probably want is setInterval : 你可能想要的是setInterval

setInterval(onTheMinFunc, delay);  

As is, your code using setTimeout means that the time it takes to execute your onTheMinFunc is being added into your delay before the next one is started, so over time, this extra delay will add up. 因此,使用setTimeout的代码意味着执行onTheMinFunc所需的时间会在下一个启动之前添加到您的延迟中,因此随着时间的推移,这个额外的延迟将会增加。

Using setInterval will be more accurate, since the delay is between calls to execute the function, rather than starting the timer only after the function is finished. 使用setInterval会更准确,因为延迟是在执行函数的调用之间,而不是仅在函数完成后启动计时器。

Timers and javascript times aren't very accurate, and I would think the only way to make sure a function is executed every whole minute over time, is to check the seconds every second 定时器和javascript时间不是很准确,我认为确保函数每隔一段时间执行一次的唯一方法是检查每秒的秒数

setInterval(function() {
    if ( new Date().getSeconds() === 0 ) onTheMinFunc();
},1000);

FIDDLE 小提琴

I think you want something closer to this: 我想你想要更接近这个:

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();

caveat: I did not thoroughly test this for timing. 警告:我没有彻底测试这个时间。 But it appeared to work for 1 sec intervals and 1 min intervals well enough. 但它看起来间隔1秒,间隔1分钟。

This has the advantage of not recalculating every second, and also not just starting a 60 second timer from whatever the current time is. 这样做的好处是不会每秒重新计算,也不仅仅是从当前时间开始计时60秒。

Here is a slight modification to your code: 以下是对代码的略微修改:

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

It recalculates the number of milliseconds to wait till the next minute every time so it is as accurate as possible to the top of the minute. 它会重新计算每次等到下一分钟的毫秒数,以便尽可能准确地达到分钟的最高点。

The current accepted answer may overkill 目前接受的答案可能有点过分

Executing if ( new Date().getSeconds() === 0 ) onTheMinFunc(); 执行if ( new Date().getSeconds() === 0 ) onTheMinFunc(); on each second (and forever) seems to not be a good idea. 每一秒(永远)似乎不是一个好主意。

I will not benchmark it against the following propositions, it's not necessary. 我不会将它与以下命题进行对比,这是没有必要的。

Clues 线索

  1. Use whatever logic is necessary to calculate the start moment . 使用任何必要的逻辑来计算开始时刻
  2. On the start moment 开始的那一刻

    1. Use setInterval for remaning executions 使用setInterval重新执行执行
    2. Execute the first call 执行第一个电话

      • Note setInterval is called ASAP to avoid that time lapses. 注意 setInterval被称为ASAP以避免时间过去。

If you want that new Date().getSeconds() === 0 : 如果你想要那个new Date().getSeconds() === 0

var id = setInterval(function() {
    if ( new Date().getSeconds() === 0 ) {
        setInterval(onTheMinFunc, delay);
        onTheMinFunc();
        clearInterval(id);
    }
},1000);

Alternatively, you could use your own logic: 或者,您可以使用自己的逻辑:

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

Please check both examples working on jsfiddle 请检查两个关于jsfiddle的示例

The second (Example B) seems more accurate. 第二个(例B)似乎更准确。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM