Подтвердить что ты не робот

JavaScript setTimeout и изменения системного времени вызывают проблемы

Я заметил, что если бы я установил setTimeout в течение 1 минуты в будущем, а затем изменил свое системное время на 5 минут в прошлом, функция setTimeout запустится через 6 минут.

Я сделал это потому, что хотел видеть, что происходит во время перехода на летнее время на системные часы.

На моей веб-странице в JavaScript используется функция setTimeout для автоматического обновления страницы каждые 5 секунд, и, если произойдет переход на летнее время, информация о странице замерзнет в течение часа. Есть ли способ обхода?

Изменить: обновляю страницу с помощью Ajax, я не хочу обновлять всю страницу.

4b9b3361

Ответ 1

Что я сделаю, так это изменение от открытия нового запроса Ajax каждые 5 секунд, чтобы использовать Comet (длительный опрос). Это лучший вариант, потому что сервер будет каждый раз вносить новые результаты в браузер каждый раз, когда они понадобятся, это может быть каждые 5 секунд на стороне сервера или каждый раз, когда доступна новая информация.

Еще лучше было бы использовать сетевые сокеты и вернуть Comet. Это легко реализовать с помощью Faye или socket.oi.

Существуют и другие варианты, такие как CometD o Ape.

Ответ 2

Используйте setInterval вместо setTimeout, и ваши проблемы должны быть решены:)

Update:

Если вы действительно не можете использовать setTimeout или setInterval, вы можете попробовать иметь скрытую iframe, которая загружает простую HTML-страницу, которая выглядит примерно так:

<html>
    <head>
        <meta http-equiv="refresh" content="300"/>
        <script>
            document.domain='same as parent page';
            top.ajax_function_you_wish_to_trigger();
        </script>
    </head>
    <body>
    </body>
</html>

Если вам повезет, обновление meta не вызовет у вас те же проблемы.

Другим решением было бы переместить запуск события на сервер с помощью server push. Есть много причин не делать этого, не в последнюю очередь, чтобы вы централизовали события и делали их обузой на сервере, но это можно было бы считать последним средством.

Ответ 3

Вы можете использовать обновление метатега для этого. Этот код обновит страницу каждые 5 секунд:

<meta http-equiv="refresh" content="5"> 

Что касается javascript-вопроса, возможно, именно так, как браузер обрабатывает setTimeout. Он сообщает браузеру, что он выполняет код в установленное время, а затем, когда часы меняются, код все еще выполняется в то время до изменения тактового сигнала? Просто догадаться, но мне придется помнить об этом в следующий раз, когда я использую setTimeout.

Изменить: Хорошо, это не сработает для ajax Изменить снова: это действительно хороший вопрос. Я уверен, что setTimeout функционирует, как я сказал выше, но ничего себе, это мозговой тизер.

Ответ 4

Вы можете вытащить и выполнить проверку if (Date in range foo). В основном проверьте, находится ли текущая отметка времени в течение 5 секунд от летнего времени, а затем просто обновите страницу, а затем, используя setTimeout.

Таким образом, пользователи получают незначительное раздражение вблизи известного изменения времени, но страница не будет зависеть в течение часа.

Ответ 5

Недавно я столкнулся с этой проблемой. В моем случае изменение времени может привести к серьезным финансовым потерям, поэтому мне пришлось серьезно относиться к этому.

Некоторая предыстория:

  • IE и Opera обрабатывают правильное изменение времени системы (никаких побочных эффектов для setTimeout, setInterval).
  • FF < 4.0, и браузер, основанный на Webkit, не справляется с изменением времени до прошлого (точно так же, как описано). Примечание: таймеры в Chrome, однако, останавливаются только через некоторое время ~ 2-60 с.

Мое решение: используйте какое-либо событие из пользовательского взаимодействия (т.е. mousemove, mouseove и т.д.), чтобы вызвать проверку изменения времени.

Clock.prototype.checkLocalTime = function(){
var diff = Date.now()- this.lastTimestamp;
if ( diff < 0 || diff > 20000) { // if time shifted back or more than 20s to the future
    console.warn('System time changed! By ' + diff + 'ms' );
    this.restartTimer();
    this.getServerTime();
}
this.lastTimestamp = time;

}

Как вы можете заметить, я перезапускаю таймер и дополнительно синхронизую время с сервером.