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