Таймер отстаёт в фоновой вкладке: как считать оставшееся время
Если обратный отсчёт отстаёт после возвращения во вкладку, не считайте прошедшее время по количеству вызовов таймера. Храните принятый момент окончания и при обновлении пересчитывайте разницу с текущим временем. Срабатывание callback — повод обновить экран, а не доказательство, что прошла ровно одна секунда. Для серверной брони её состояние подтверждает сервер.
Две разные задачи: обновить цифры и определить срок
В учебном варианте программа хранит «осталось 180 секунд» и уменьшает число на единицу при каждом callback. Если за время отсутствия пользователя вызовов было меньше ожидаемого, цифры перестают соответствовать действительности. Увеличение частоты обновления не исправляет сам принцип измерения времени.
Документация setTimeout описывает задержки в неактивных вкладках и позднее выполнение, когда браузер занят. Конкретные условия зависят от браузера и его состояния. Поэтому обещание «этот вызов всегда приходит каждую секунду» нельзя делать основой пользовательского срока.
Определите, кто владеет дедлайном
У локального упражнения, брони товара и срока ответа поддержки могут быть разные правила. Сначала уточните, продолжает ли срок идти при закрытой странице, можно ли его продлить и какая система принимает окончательное решение. Отображение нельзя исправить без этого договора: возможно, в задаче нужен вовсе не непрерывный отсчёт, а пауза активности.
Для веб-приложения с серверной бронью храните и передавайте согласованный момент окончания вместе с актуальным состоянием. Уточните формат времени и его смысл. Нельзя заново выдавать полный интервал при каждом открытии страницы, если пользователь возвращается к той же броне с уже прошедшей частью срока.
Считайте остаток, а callback используйте для показа
Принцип расчёта: оставшееся время равно разнице между дедлайном и принятым текущим временем, с ограничением снизу нулём. Отдельно согласуйте округление для показа секунд. При новом обновлении вычисляйте разницу снова, а не вычитайте единицу из старой надписи.
Учебный пример: дедлайн принят на 12:03, начало показа — 12:00. После возврата в 12:02 остаётся одна минута, даже если отработало только сорок обновлений. Старый счётчик показал бы 140 секунд вместо 60. Числа здесь иллюстрируют арифметику, а не измеренную политику конкретного браузера.
Таблица переходов после отсутствия пользователя
Ниже собственный договор отображения для условной серверной брони. Время во всех строках относится к одной согласованной шкале. Локальные часы устройства нельзя молча принимать за эту шкалу, если они могут отличаться от источника срока.
| Учебная ситуация | Что известно | Что показываем | Что подтверждает сервер | Следующее действие |
|---|---|---|---|---|
| Открытие в 12:00 | Дедлайн 12:03, состояние получено | Три минуты по принятым правилам округления | Действительность брони на момент ответа | Периодически пересчитывать отображение |
| Возврат в 12:02 | Тот же дедлайн 12:03 | Одна минута после пересчёта | Актуальное состояние при сверке | Обновить данные, если этого требует договор |
| Возврат в 12:04 | Сохранённый срок уже в прошлом | Ноль и понятное состояние проверки | Истекла ли бронь или была изменена | Не выдавать локальный ноль за подтверждённую отмену |
| Получено продление до 12:05 в 12:02 | Новый подтверждённый дедлайн | Три минуты от нового срока | Что продление принято | Заменить старый дедлайн, не создать второй отсчёт |
| Связь недоступна после возврата | Есть только прежний снимок | Отметка о необходимости уточнения | Пока нет свежего подтверждения | Дать понятный способ повторной сверки |
Возврат во вкладку — причина обновить представление
Page Visibility API позволяет узнать об изменении видимости документа через visibilitychange. Когда пользователь возвращается, пересчитайте показ и при необходимости запросите актуальное состояние. У события другая задача: оно сообщает о видимости, а не гарантирует точное выполнение в момент истечения срока.
Не пытайтесь проиграть все пропущенные экранные секунды после возвращения. Человеку нужно актуальное состояние сейчас. Если экран создаёт новые обработчики при каждом открытии, проверьте, что прежние не продолжают менять надпись параллельно. Иначе уже исправленная формула может получать противоречащие друг другу обновления.
Часы устройства и время сервера могут разойтись
Если дедлайн принадлежит серверу, договоритесь, как клиент соотносит своё время с ответом. Это отдельная часть реализации с сетевой задержкой, повторной сверкой и поведением при изменении часов. Прямое вычитание серверного момента из непроверенных локальных часов не обеспечивает правильный результат само по себе.
В API-интеграции различайте приблизительную надпись для человека и решение о допустимости операции. Проверку брони или доступа выполняет владелец этих данных. Не обещайте, что попытка в последнюю отображаемую секунду обязательно будет принята: запросу ещё предстоит обработка по согласованным правилам.
При нуле не придумывайте результат операции
Отсчёт может достичь нуля, пока система продлевает срок или пользователь уже завершил действие в другой вкладке. Поэтому состояния «по прежним данным срок прошёл», «подтверждено истечение» и «нет связи» стоит различать. Иначе интерфейс покажет отмену даже там, где серверное действие завершилось успешно.
Для SaaS-платформы выберите безопасное поведение в период уточнения. Например, показать ожидание проверки и не создавать дублирующую бронь без подтверждения предыдущего результата. Конкретные доступные действия определяются процессом, а не тем, что надпись стала красной.
Как принять исправление без обхода ограничений браузера
- На учебной операции зафиксируйте владельца срока, дедлайн и способ подтверждения состояния. Не используйте рабочий заказ клиента.
- Сравните обычный показ и возвращение после скрытой вкладки. Проверяйте пересчитанный остаток, а не число промежуточных срабатываний.
- Вернитесь после окончания сохранённого срока. Интерфейс должен различать локальный расчёт и подтверждение от системы.
- Получите учебное продление и убедитесь, что оно заменило прежний срок во всех нужных местах.
- Проверьте недоступность сети и изменение локальных часов. Показываемое состояние не должно выдавать отсутствие данных за установленный результат.
- Повторно откройте страницу и убедитесь, что не создан новый полный срок или несколько конкурирующих обновлений для одной операции.
Не используйте фиктивное аудио, бесконечные циклы и имитацию активности ради удержания таймера. Исправление должно работать с обычным жизненным циклом страницы. Готовность подтверждается актуальным остатком и честным состоянием после возвращения, а не количеством потреблённых ресурсов в фоне.
Вопросы и ответы
Почему setTimeout замедляется в background tab?
Браузеры ограничивают фоновые таймеры, а занятость среды тоже может задержать выполнение. Не используйте количество вызовов как измерение прошедшего времени.
Поможет ли setInterval в background tab вместо setTimeout?
Смена механизма периодического вызова не делает число срабатываний надёжными часами. Для отсчёта от принятого дедлайна пересчитывайте остаток независимо от количества обновлений.
Как использовать Page Visibility API для таймера?
При возвращении к видимому документу обновите отображение и при необходимости уточните состояние у сервера. API видимости не подтверждает истечение брони и не заменяет источник времени.