Как сделать таймер: setInterval и обратный отсчёт
Повторять действие через равные промежутки умеет setInterval, остановить его — clearInterval. Обратный отсчёт от трёх в Node.js:
let seconds = 3;
const timerId = setInterval(() => {
console.log(seconds);
seconds--;
if (seconds === 0) {
clearInterval(timerId);
console.log("Время вышло!");
}
}, 1000);3
2
1
Время вышло!setInterval(функция, мс)вызывает функцию каждыемсмиллисекунд и возвращает номер таймера.clearInterval(номер)останавливает его. Без остановки интервал работает вечно.setTimeout(функция, мс)— один вызов черезмсмиллисекунд; отменяется черезclearTimeout.
Таймер на странице
Разметка — табло и две кнопки:
<p id="clock">05:00</p>
<button id="start">Старт</button>
<button id="stop">Стоп</button>Код:
const clock = document.querySelector("#clock");
let left = 5 * 60;
let timerId = null;
function show() {
const m = String(Math.floor(left / 60)).padStart(2, "0");
const s = String(left % 60).padStart(2, "0");
clock.textContent = `${m}:${s}`;
}
document.querySelector("#start").addEventListener("click", () => {
if (timerId !== null || left === 0) {
return;
}
timerId = setInterval(() => {
left--;
show();
if (left === 0) {
clearInterval(timerId);
timerId = null;
clock.textContent = "Время вышло!";
}
}, 1000);
});
document.querySelector("#stop").addEventListener("click", () => {
clearInterval(timerId);
timerId = null;
});«Старт» запускает отсчёт пяти минут, «Стоп» ставит его на паузу, повторный «Старт» продолжает с того же места. padStart(2, "0") дописывает ноль слева: 5 → 05.
Проверка timerId !== null в начале обработчика важна: без неё каждое нажатие «Старт» запускает ещё один интервал, и время бежит вдвое, втрое быстрее, а «Стоп» останавливает только последний.
Почему таймер отстаёт
setInterval не обещает точности: вызов может случиться позже, если браузер занят. А в неактивной вкладке браузеры нарочно вызывают таймеры реже, чтобы экономить заряд. За несколько минут счётчик «каждую секунду минус один» заметно отстаёт от настоящих часов.
Для точного отсчёта запомните момент окончания и на каждом шаге считайте, сколько до него осталось:
const clock = document.querySelector("#clock");
const end = Date.now() + 5 * 60 * 1000;
const timerId = setInterval(() => {
const left = Math.max(0, Math.round((end - Date.now()) / 1000));
const m = String(Math.floor(left / 60)).padStart(2, "0");
const s = String(left % 60).padStart(2, "0");
clock.textContent = `${m}:${s}`;
if (left === 0) {
clearInterval(timerId);
}
}, 250);Date.now() — текущее время в миллисекундах. Даже если какой-то вызов опоздал, следующий покажет верное время. Интервал здесь короче секунды, чтобы табло не перескакивало через цифры.
Секундомер
Для секундомера — то же самое наоборот: запомните момент старта и выводите, сколько прошло: Math.floor((Date.now() - start) / 1000) секунд.