Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/471.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 每分钟在分钟上调用函数_Javascript - Fatal编程技术网

Javascript 每分钟在分钟上调用函数

Javascript 每分钟在分钟上调用函数,javascript,Javascript,我写的每分钟调用一个函数的代码,我认为是有缺陷的,因为它在一段时间内是好的,但在页面加载后,每小时会落后大约15秒。老实说,我不知道是什么原因导致了滞后,也许是函数执行所需的时间,小的失误累积起来了。是否有一种方法可以自动更正函数中调用的错误。或者可能有人知道一种更好的方法来实现即时函数调用。非常感谢任何帮助或想法。谢谢 var now = new Date(); var delay = 60 * 1000; // 1 min in msec var start = delay - (now.g

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

首先,DOM Timers API不能保证准确性:

此API不能保证计时器完全按计划运行。CPU负载、其他任务等导致的延迟是可以预料的

第二,由于执行
onTheMinFunc()
的时间,每一轮都会有一个延迟(您仅在完成时设置超时)

所以,让我们假设
onTheMinFunc
执行需要半秒的时间-每分钟会有半秒的延迟,并且它会累积-仅10分钟后,它会延迟相当多。(注意,执行功能通常不应超过15毫秒,以避免明显的滞后)

尝试:

还是不太准确。您可以在更短的时间间隔内进行轮询,并跟踪日期变量,但同样没有保证。

您可能想要的是:

同样,使用
setTimeout
的代码意味着在下一次启动之前,执行
onTheMinFunc
所需的时间将被添加到延迟中,因此随着时间的推移,这个额外的延迟将累积起来


使用
setInterval
会更准确,因为延迟是在执行函数的两次调用之间,而不是在函数完成后才启动计时器。

计时器和javascript时间不是很准确,我认为确保函数在一段时间内每整分钟执行一次的唯一方法,就是每秒检查秒数

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

我想你想要更接近这一点的东西:

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秒间隔和1min间隔内都能正常工作


这样做的好处是不需要每秒重新计算,也不需要从当前时间开始60秒的计时器。

下面是对代码的轻微修改:

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);
它会重新计算每次等待到下一分钟的毫秒数,以便尽可能精确到分钟的顶端。

当前接受的答案可能过多 在函数()上执行if(new Date().getSeconds()==0)时的
在每一秒(和永远)似乎不是一个好主意

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

线索
  • 使用任何必要的逻辑来计算开始时刻
  • 开始时刻

  • 使用
    setInterval
    进行还押执行
  • 执行第一个调用

    • 注意
      setInterval
      被称为ASAP以避免时间流逝
  • 如果您想要新日期().getSeconds()==0
    var id=setInterval(函数(){
    如果(新日期().getSeconds()==0){
    设置时间间隔(onTheMinFunc,延迟);
    onTheMinFunc();
    清除间隔(id);
    }
    },1000);
    
    或者,您可以使用自己的逻辑:
    var now=newdate();
    var延迟=60*1000;//1分钟(毫秒)
    var start=delay-(now.getSeconds())*1000+now.getmillizes();
    setTimeout(函数(){
    设置时间间隔(onTheMinFunc,延迟);
    onTheMinFunc();
    },开始);
    
    请查收
    第二个(示例B)似乎更准确。

    只是出于好奇,为什么不使用
    setInterval(setTimer,delay)?我认为这不应该每60秒发生一次,而是根据系统时钟在一分钟的第0秒发生。@rob M我已经完成了,但问题是相同的,我需要先使用超时来抵消时间差。如果有人在10:00:40加载页面。它将在20年内第一次调用该函数seconds@user2014429也许我加入有点晚了,但请检查我的答案。这是我突然想到的。我希望避免它,但我认为你可能是对的,这可能是最好的解决办法。谢谢。这永远不会正常工作-getSeconds不太可能精确为0,因为@mplungjan getSeconds是一个介于0和59之间的数字,所以它将是时间的0 1/60。get毫秒不太可能精确为零,但由于get seconds将整秒的毫秒值舍入,这应该是正确的几乎,如果不是所有的1秒。可以想象,它可能会错过整整一秒钟的检查,但所需的处理量可能会破坏您的页面。在任何情况下,我认为检查每一秒对于你想要的精度来说都是多余的。@Andrew-不确定为什么这么难获得,但这会很好,并且每一秒使用一次日期对象所需的处理非常小,普通手表可能可以做到这一点,所以这永远不会是一个问题。谢谢你的解释。我认为你是对的,为了确保准确性,往往更好。我认为像阿德内奥这样的答案是正确的。谢谢。@user2014429那很好-我很高兴能帮助你-祝你好运。看起来是个好办法。我现在正在测试。如果你能在15分钟左右看到问题是否解决,我会告诉你的。谢谢
    
    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();
    
    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);