Что происходит с setTimeout, когда компьютер переходит в спящий режим? - PullRequest
56 голосов
/ 14 июня 2011

Предположим, что в современном веб-браузере я делаю setTimeout в течение 10 минут (в 12:00) и спустя 5 минут, чтобы перевести компьютер в спящий режим, что должно произойти, когда система снова проснется?Что произойдет, если он проснется до истечения 10 минут (в 12:09) или намного позже (в 16:00)?

Причина, по которой я спрашиваю, заключается в том, что я хотел бы получить новыйТокен аутентификации запрашивается каждые 10 минут, и я не уверен, что браузер поступит правильно и немедленно запросит новый токен, если он проснется через долгое время.

Пояснения : я не хочу использовать куки - я пытаюсь создать здесь веб-сервис;и да, сервер будет отклонять старые и недействительные токены.

Ответы [ 7 ]

45 голосов
/ 14 июня 2011

Насколько я тестировал, он просто останавливается и возобновляет работу после пробуждения компьютера.Я полагаю, это означает, что для сеанса в зависимости от setTimeout/Interval счетчик включается с момента, когда компьютер заснул.

Я не думаю, что вы должны полагаться на точность setTimeout/Interval для критичных ко времени вещей.Для Google Chrome I недавно обнаружил , что любой тайм-аут / интервал (короче 1 с) будет замедлен до одного раза в секунду, если вкладка, на которой он активирован, теряет фокус.

Кроме того, точность тайм-аутов / интервалов зависит от других запущенных функций и т. Д. Короче говоря: это не очень точно.

Поэтому, используя интервал и тайм-ауты, сверяйте время с временем запуска в течениезапускаемая им функция даст вам лучшую точность.Теперь, если вы начнете в 12:00, компьютер перейдет в спящий режим и проснется в 16:13 или около того, проверяя 16:13 против 12:00, вы уверены, что вам нужно обновить токен.Пример использования сравнения времени можно найти здесь

6 голосов
/ 03 февраля 2016

Сравните текущую дату и время с датой, когда страница была загружена, например:

//Force refresh after x minutes.
var initialTime = new Date();
var checkSessionTimeout = function () {
    var minutes = Math.abs((initialTime - new Date()) / 1000 / 60);
    if (minutes > 20) {
        setInterval(function () { location.href = 'Audit.aspx' }, 5000)
    } 
};
setInterval(checkSessionTimeout, 1000);
4 голосов
/ 14 июня 2011

Поведение зависит как от браузера, так и от операционной системы. ОС обрабатывает спящий режим, и отдельные приложения часто не учитывают его.

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

Если это действительно проблема, вы, вероятно, захотите быть в большей безопасности, чем сожалеть, и сохранить отметку времени, когда токен был инициализирован, и использовать setInterval для периодической проверки (скажем, дважды в минуту).

Однако безопасность не должна быть просто предметом на стороне клиента. Убедитесь, что ваш сервер выдает ошибку, если используется старый / недействительный токен, и что Ajax ведет себя соответствующим образом в ответ.

[править] Я согласен с другим постом, что он может срабатывать сразу после следующего тика. Блог Ресига очень хорош.

3 голосов
/ 16 июля 2016

Вот мой код:

<!doctype html>
<html>

<body>
<input type="button" name="clickMe" id="colourButton" value="Start Timer" onclick="setTimeout('alert(\'Surprise!\')', 120000)"/>

</body>
<script>


</script>
</html>

Я взял три сценария, которые могли бы ответить на вопрос.

Сценарий 1: В 00 секунд нажмите кнопку «Таймер запуска». В 25 секунд компьютер засыпает. В 1мин 40 секунд просыпается компьютер. Через 2 минуты отображается предупреждение.

Сценарий 2: В 00 секунд нажмите кнопку «Таймер запуска». В 26 секунд компьютер засыпает. В 3 минуты я просыпаюсь компьютер. Оповещение отображается.

Сценарий 3: Это действительно поразительно.

<input type="button" name="clickMe" id="colourButton" value="Start Timer" onclick="setTimeout('alert(\'Surprise!\')', 600000)"/>

В 00 секунд я нажимаю кнопку «Таймер запуска». Примерно в течение 1 минуты 30 секунд компьютер находится в режиме гибернации (моему компьютеру требуется минута для запуска режима гибернации)

Через 8 минут я включаю ноутбук. Ровно через 10 минут появляется предупреждение.

PS: This is my first ever comment on Stack Exchange. I prefer to execute code and view results rather than infer from theory.
2 голосов
/ 23 октября 2017

Основываясь на ответе Бена, я создал следующую утилиту.Вы можете настроить длительность выборки, но я использую ее для обновления токена:

const absoluteSetInterval = (handler, timeout) => {
  let baseTime = Date.now();
  const callHandler = () => {
    if (Date.now() - baseTime > timeout) {
      baseTime = Date.now();
      handler();
    }
  };
  return window.setInterval(callHandler, 1000);
};

const absoluteClearInterval = (handle) => window.clearInterval(handle);
2 голосов
/ 06 января 2017

Поведение таймеров JavaScript (setTimeout) в нескольких сценариях.

  1. Когда поток свободен и время ожидания истекло: таймер срабатывает сразу после времени ожидания.Это может иметь определенную неточность около 0-5 мс (типичный сценарий).
  2. Когда поток слишком занят (огромный цикл) достаточно долго, чтобы пройти тайм-аут таймера: Таймер будет выполнен сразу после того, как потокосвобождается.
  3. Когда появляется предупреждение: такое же поведение, что и 2.
  4. Когда поток приостановлен из-за того, что наш ноутбук перешел в спящий режим: я видел несколько вещей.Но наиболее распространенной является полная неточность и игнорирование времени, проведенного во время сна.

Поскольку таймеры в JavaScript основаны на тиках процессора, а процессор спит, то таймер полностью приостанавливается и возобновляется как 'поскольку ничего бы не случилось ».

0 голосов
/ 14 июня 2011

В блоге Джона Ресига таймеры, как говорят, используют "настенные часы". Я считаю, что события будут срабатывать сразу после возобновления работы машины, потому что setTimeout () не гарантирует, что выполнение - это конкретный момент времени, но как можно скорее после указанного интервала. Однако я сам не проверял.

...