setInterval会漂移吗?

时间:2009-06-12 08:53:18

标签: javascript setinterval

这真是一个非常简单的问题。如果我使用setInterval(something, 1000),我是否可以完全确定在31天之后它会恰好60*60*24*31次触发“某事”?或者是否存在所谓漂移的风险?

3 个答案:

答案 0 :(得分:30)

简短回答:不,你不能确定。是的,它可以漂移。

答案很长:约翰Resig在Accuracy of JavaScript TimeHow JavaScript Timers Work

从第二篇文章:

  

为了理解定时器如何在内部工作,需要探索一个重要的概念:不能保证定时器延迟。由于浏览器中的所有JavaScript都在单个线程上执行,因此异步事件(例如鼠标单击和计时器)仅在执行中打开时运行。

这两篇文章(以及该网站上的任何内容)都是很好的阅读,所以也可以。

答案 1 :(得分:19)

这是您可以在Firefox中运行的基准:

var start = +new Date();
var count = 0;
setInterval(function () {
    console.log((new Date() - start) % 1000,
    ++count,
    Math.round((new Date() - start)/1000))
}, 1000);

第一个值应该尽可能接近0或1000(任何其他值表示触发器的定时“异地”。)第二个值是代码被触发的次数,第三个值是可以 触发的次数是多少次。你会注意到,如果你占用了你的CPU它可以完全离开现场,但它似乎纠正自己。尝试运行它更长的时间,看看它是如何处理的。

答案 2 :(得分:1)

(抱歉我的英文不好) 我有关于倒计时功能的同样问题,我写了一个函数countdown()并使用setInterval循环,但每个循环漂移1-3毫秒。然后我写了一个控制任何漂移并修复它的函数。

它只用真实的分钟和秒来控制。这里是。它对我来说很好,我希望它也能帮到你。

$.syncInterval(functionname,interval,controlinterval)

示例:

countdown(){ some code };
$.syncInterval(countdown,1000,60);

它表示每1000毫秒运行倒计时功能并每60秒检查一次

这是代码:

$.syncInterval = function (func,interval,control) { 
        var 
        now=new Date();
        realMinute=now.getMinutes(),
        realSecond=now.getSeconds(),
        nowSecond=realSecond,
        nowMinute=realMinute,
        minuteError=0,
        countingVar=1,
        totalDiff=0;

        var loopthat = setInterval(function(){

        if (nowSecond==0) {
            nowMinute++;
            nowMinute=nowMinute%60;
        };
        if (countingVar==0){

            now=new Date();
            realSecond=now.getSeconds();
            realMinute=now.getMinutes();

            totalDiff=((realMinute*60)+(realSecond))-((nowMinute*60)+(nowSecond));
            if(totalDiff>0){
                for (i=1;i<=totalDiff;i++) {
                    func();
                    nowSecond++;
                    countingVar++;
                };
            } else if (totalDiff==0){
                func();
                nowSecond++;
                countingVar++;
            } else if (totalDiff<0) {

            };
        } else {
            func();
            nowSecond++;
            countingVar++;
        };
        countingVar=countingVar%control;
        nowSecond=nowSecond%60;
    },interval);
};