Javascript не обновляет таймер через некоторое время

Я протестировал простой код таймера для отображения таймера на веб-сайте. Таймер работает нормально, когда я нахожусь на странице. Но когда я перехожу на другую страницу или сайт, через некоторое время, когда я возвращаюсь на страницу таймера, я вижу, что таймер не работал правильно в интервале.
Предположим, я ухожу со страницы на 5 минут. Так что когда вернусь, надо посмотреть 00:05:00. Но отображается 00:01:00 (вокруг). Но если я не покидаю страницу, все работает нормально.
Каково решение?

timerElement = document.getElementById("time");
let seconds = 0, minutes = 0,  hours = 0;
timerInterval = setInterval(function() {
  seconds++;

  if (seconds === 60) {
    seconds = 0;
    minutes++;

    if (minutes === 60) {
      minutes = 0;
      hours++;
    }
  }

  const formattedTime = `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`;
  timerElement.textContent = formattedTime;
}, 1000);
<h1 id = "time"></h1>

Даже я разместил это на странице github. Но результат тот же.

Некоторые браузеры, например Microsoft Edge, автоматически переводят ваши вкладки в спящий режим после некоторого времени бездействия.

derloopkat 19.09.2023 00:24

Во-первых, не используйте такие вещи, как hours++ внутри интервала, используйте объект Date и сравните его с некоторой датой начала.

Keith 19.09.2023 00:39

Аргумент задержки в setInterval() нельзя использовать для хронографической задачи.

Mister Jojo 19.09.2023 00:59

если вы хотите, чтобы он был действительно надежным, не увеличивайте секунды, а вместо этого рассчитайте окончательную метку даты и сохраните ее в localStorage. Затем при отображении счетчика всегда сравнивайте текущую метку даты с меткой в ​​localStorage, чтобы вычислить оставшиеся секунды.

Rick 19.09.2023 01:53
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
4
98
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

const
  timerElement = document.querySelector('#timer-element')
, Digits2      = t => t<10 ? `0${t}` : t
, one_Sec      = 1000
, one_Min      = one_Sec * 60
, one_Hour     = one_Min * 60
, ZeroTime     = new Date().getTime()
  ;
setInterval(()=>
  {
  let tim = new Date().getTime() - ZeroTime
    , h   = Math.floor( tim / one_Hour)
    , m   = Math.floor((tim % one_Hour) / one_Min )
    , s   = Math.floor((tim % one_Min ) / one_Sec )
    ;
  timerElement.textContent = `${Digits2(h)}:${Digits2(m)}:${Digits2(s)}`
  },500);
<h1 id = "timer-element"></h1>

Если вы ищете более подробную информацию: см. там

Ответ принят как подходящий

setInterval и setTimeout вызывают обратный звонок не в точное время. Когда страница находится на скрытой вкладке, браузер может отложить/регулировать обратные вызовы.

Я бы предложил попробовать requestAnimationFrame (который не вызывается на скрытой вкладке, и это хорошо) и сравнить текущее время со временем начала таймера. Использование requestAnimationFrame позволит более точно обновлять таймер на экране.

Форматирование можно выполнить с помощью Intl.DateTimeFormat (используется здесь для упрощения примера, требуются некоторые настройки для обработки часов > 24):

const start = new Date, today = new Date;
today.setHours(0, 0, 0, 0);
let running = true;

const format = new Intl.DateTimeFormat('en', {
  hourCycle: 'h23',
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit',  
  fractionalSecondDigits: 2
});
// add today's timestamp so the timezone would be properly handled
const timer = () => requestAnimationFrame(() => {
  $time.textContent = format.format(new Date - start + +today);
  running && timer();
});

timer();
console.info('started');
button{
  padding: 10px;
  min-width: 100px;
  border-radius: 5px;
  cursor:pointer;
  background:lightblue;
}
<h1 id = "$time" style = "font-family:monospace"></h1>
<button onmousedown = "running = false">Stop</button>

Другие вопросы по теме