Будет ли установлен Интервал дрифта? - PullRequest
36 голосов
/ 12 июня 2009

Это довольно простой вопрос на самом деле. Если я использую setInterval(something, 1000), могу ли я быть полностью уверен, что, скажем, через 31 день это вызовет "что-то" ровно 60*60*24*31 раз? Или есть риск так называемого дрифта?

Ответы [ 3 ]

30 голосов
/ 12 июня 2009

Краткий ответ: Нет, вы не можете быть уверены. Да, это может дрейфовать.

Длинный ответ: Джон Резиг о Точности времени JavaScript и Как работают таймеры JavaScript .

Из второй статьи:

Чтобы понять, как таймеры работают внутри, необходимо изучить одну важную концепцию: задержка таймера не гарантируется. Поскольку весь JavaScript в браузере выполняется в одном потоке, асинхронные события (такие как щелчки мыши и таймеры) запускаются только тогда, когда в ходе выполнения было открытие.

Обе статьи (и все, что на этом сайте) отлично читаются, так что имейте это в виду.

19 голосов
/ 12 июня 2009

Вот эталонный тест, который вы можете запустить в 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, насколько это возможно (любое другое значение показывает, насколько «вне места» было время срабатывания триггера.) Второе значение - это число раз, когда код был запущен, а третье значение - сколько раз мог должен сработать. Вы заметите, что если вы перегружаете свой процессор, он может оказаться совсем не на месте, но, похоже, он сам себя исправит. Попробуйте запустить его в течение более длительного периода времени и посмотрите, как он справляется.

1 голос
/ 29 апреля 2013

(извините за мой плохой английский) У меня была та же проблема с функцией обратного отсчета, я написал функцию 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);
};
...