Будет setInterval дрейф?

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

Ответ 1

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

Ответ 2

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

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

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

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

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

Ответ 3

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