В JavaScript существует возможность задавать способ исполнения кода не только синхронным образом, но и асинхронно, благодаря взаимодействию js с внутренним планировщиком среды выполнения кода. К примеру, нам необходимо запустить некоторый js-код через определенный промежуток времени разово либо постоянно с повторением через заданный интервал. Для реализации такой задержки в JavaScript существуют методы setTimeout
и setInterval
. В этой статье рассмотрим, как работают эти два метода, а также создадим таймер на js во всплывающем окне с использованием вышеуказанных методов на нативном js и с помощью библиотеки jQuery.
Таймер на JavaScript (jQuery): описание задачи и верстка
Прежде чем перейти к разбору методов setTimeout
и setInterval
, сперва опишем назначение создаваемого таймера и создадим заготовку на HTML и CSS.
Предположим, мы хотим реализовать на сайте рекламный блок с акцией на товар либо услугу. Этот блок будет содержать таймер, отсчитывающий время до конца акции. По завершении обратного отсчета будет появляться сообщение об истечении времени. Рекламный блок будет появляться через определенное время после открытия пользователем страницы.
Первым делом создадим HTML-разметку для будущего блока: установим тексты акции и сообщения о ее окончании, поля для минут и секунд таймера, а также кнопку, при нажатии на которую подразумевается переход на страницу с рекламной акцией. Но в нашем случае нет необходимости добавлять на кнопку конкретную ссылку. Вместо этого мы реализуем остановку таймера при нажатии на эту кнопку. Разметка будет выглядеть следующим образом:
<div class='demoTimerPopupWrapper' id='demoTimerPopupWrapper'> <article class='demoTimerPopup'> <h3 class='demoTimerPopup__title'>Акция!</h3> <div class='demoTimerPopup__text'> <p><span class='accent'>50% скидка</span> на подписку на все курсы по программированию!</p> <p class='center'>До конца осталось:</p> </div> <div class='demoTimerPopup__timer' id='demoTimerCounter'> <input type='text' id='demoTimerMinutes' readonly> <input type='text' id='demoTimerSeconds' readonly> </div> <div class='demoTimerPopup__expired' id='demoTimerExpired'> Акция завершена! </div> <div class='demoTimerPopup__button'> <a href='#' id='demoTimerAction'>Успеть!</a> </div> <div class='demoTimerPopup__close' id='demoTimerClose'>x</div> </article> </div>
Далее добавим CSS-стили:
.demoTimerPopupWrapper { position: fixed; top: 0; left: 0; width: 100%!important; max-width: 100%!important; height: 100%!important; max-height: 100%!important; justify-content: center; align-items: center; background: rgba(204, 204, 204, 0.4); z-index: 99999; display: none; } .demoTimerPopup { background: #393939; box-shadow: 0 0 7px 2px #fff; width: 300px; max-width: 100%; max-height: 100%; padding: 26px 30px; font-size: 16px; position: relative; } .demoTimerPopup__title { color: #00c1c5; font-weight: bold; text-align: center; margin: 10px 0 10px; } .demoTimerPopup__text > p { margin-bottom: 8px!important; } .demoTimerPopup__timer { display: flex; justify-content: center; padding: 0 30%; } .demoTimerPopup__timer input[type="text"] { padding: 5px 10px; width: 44px; text-align: center; border: 2px solid #00c1c5; border-radius: 7px; } .demoTimerPopup__timer input[type="text"]:last-child { margin-left: 6px; } .demoTimerPopup__action { display: flex; justify-content: center; margin-top: 15px; } .demoTimerPopup__action a { display: inline-block; padding: 5px 10px; border-radius: 7px; background: #00c1c5; color: #fff!important; text-decoration: none; font-weight: bold; transition: 0.3s; } .demoTimerPopup__action a:hover { background: #fff!important; color: #00c1c5!important; } .demoTimerPopup__expired { text-align: center; margin-top: 15px; display: none; } .demoTimerPopup__close { width: 24px; height: 24px; color: #00c1c5; cursor: pointer; display: flex; justify-content: center; align-items: center; position: absolute; top: 0; right: 0; } .accent { color: #00c1c5; font-weight: bold; } .center { text-align: center; }
По итогу мы получим сверстанный рекламный блок, к которому будем добавлять js-код для демонстрации возможностей рассматриваемых методов:

Теперь мы готовы перейти к рассмотрению первого метода — setTimeout
.
Метод setTimеout
Этот метод предназначен для того, чтобы вызвать JavaScript-код один раз через промежуток времени. Синтаксис метода выглядит следующим образом:
const timeoutId = setTimeout(func, delay, param1, …, paramN);
func
— функция, вызываемая по истечении установленного времениdelay
.delay
— время, по истечении которого вызывается функцияfunc
. Устанавливается в миллисекундах. Например, 7000 — 7 секунд (или 7000 миллисекунд).param1, …, paramN
— список параметров, передаваемых в функциюfunc
.
Метод возвращает идентификатор таймаута, который можно использовать для отмены запуска функции func
.
Вместо функции
func
, можно передавать строку с кодом, но этот вариант не рекомендуется из соображений безопасности.
setTimeout
используем в нашем примере для появления всплывающего окна с рекламным блоком через 3 секунды. Для этого добавим этот метод в следующем виде:
setTimeout(function() { // Рекламный блок изначально скрыт с помощью CSS-свойства "display" со значением "none". // Изменим значение "display" на "flex" document.getElementById('demoTimerPopupWrapper').style.display = 'flex'; }, 3000);
Для живой демонстрации примера повесим обработчик js-кода на событие onclick
демокнопки с идентификатором startDemoTimer
. Нажав на нее и подождав три секунды, можно увидеть текущий результат — появится окно с рекламным блоком.
Акция!
50% скидка на подписку на все курсы по программированию!
До конца осталось:
Есть ли возможность отменить запуск кода функции setTimeout
после начала отсчета времени до запуска кода?
Метод clearTimеout
Как упоминалось выше, setTimeout возвращает идентификатор. Передав этот идентификатор в метод clearTimeout, мы отменим запуск функции, которая была передана методу setTimeout.
// Запустим код с задержкой и получим идентификатор const timeoutId = setTimeout(function() { document.getElementById('demoTimerPopupWrapper').style.display = 'flex'; }, 3000); // Отменим выполнения кода, переданного в setTimeout, нажатием на кнопку с идентификатором cancelTimeout // Это нужно сделать в течение трех секунд после нажатия на кнопку "Старт" document.getElementById('cancelTimeout').addEventListener('click', function() { clearTimeout(timeoutId); });
Для нашего примера этот функционал не нужен, но для демонстрации создадим еще одну кнопку, нажав на которую в течение трех секунд после нажатия на кнопку запуска, мы увидим, что всплывающее окно не сможет отобразиться.
Акция!
50% скидка на подписку на все курсы по программированию!
До конца осталось:
Теперь перейдем к созданию самого таймера обратного отсчета.
Метод setInterval
Метод setInterval
имеет идентичный методу setTimeout
синтаксис и принимает такие же параметры. Главное отличие в том, что setInterval
выполняет переданную ему функцию периодически через установленный интервал времени.
const timerId = setInterval(func, delay, param1, …, paramN);
После того как всплывающее окно появится, на нем будет работать таймер с обратным отсчетом. Метод setInterval
для такой реализации подходит идеально — каждую секунду вызывается функция, которая уменьшает текущее значение в поле для секунд на единицу, а число в поле для минут таймера будет также уменьшаться на единицу только при условии, когда секунды дошли до нуля.
Для нашего примера сделаем количество минут акции равным пятнадцати. Обновленный js-код будет выглядеть следующим образом:
// Для демонстрации запуск выполнения кода повесим на событие нажатия кнопки document.getElementById('startDemoTimer').addEventListener('click', function () { const that = this; // Заблокируем кнопку и изменим текст на ней до появления окна that.textContent = "Ждите..."; that.setAttribute('disabled', ''); setTimeout(function() { document.getElementById('demoTimerPopupWrapper').style.display = 'flex'; startDemoTimer(15, 0); // Вернем кнопке начальное состояние that.textContent = "Старт"; that.removeAttribute('disabled'); }, 3000); }); // Функция счетчика function startDemoTimer(minutes, seconds) { // Функция setValueToTimerField будет устанавливать значения минут или секунд в соответствующие поля setValueToTimerField('demoTimerMinutes', minutes); setValueToTimerField('demoTimerSeconds', seconds); // Запустим счетчик и получим его идентификатор // Функция countDemoTime будет выполняться каждую секунду const counterId = setInterval(countDemoTime, 1000); // Сохраним id счетчика в качестве значения data-атрибута в HTML-элементе с идентификатором demoTimerCounter // Это нужно, чтобы в последствии иметь возможность остановить счетчик document.getElementById('demoTimerCounter').dataset.counterId = String(counterId); } // Функция, вызываемая каждую секунду function countDemoTime() { // Возьмем текущие значения минут и секунд let currentMinutes = document.getElementById('demoTimerMinutes').value; let currentSeconds = document.getElementById('demoTimerSeconds').value; // Если секунды равны нулю, уменьшаем значение минут на единицу, а значение секунд устанавливаем в 59 // Это означает, что начинается отсчет следующей минуты в обратном порядке if (+currentSeconds === 0) { setValueToTimerField('demoTimerMinutes', --currentMinutes); setValueToTimerField('demoTimerSeconds', 59); } else { setValueToTimerField('demoTimerSeconds', --currentSeconds); } }
Однако мы не можем позволить таймеру работать бесконечно. В момент, когда поля минут и секунд станут равными нулям, мы остановим таймер и выведем сообщение о том, что время акции истекло. Такую возможность реализуем с помощью метода clearInterval
.
Метод clearInterval
Метод cleaInterval
работает подобно методу clearTimeout
: останавливает таймер по переданному идентификатору:
Дополним наш код, остановив таймер, когда он обнулится. После этого выведем сообщение. Наш итоговый код будет выглядеть следующим образом:
// Для демонстрации запуск выполнения кода повесим на событие нажатия кнопки document.getElementById('startDemoTimer').addEventListener('click', function () { const that = this; // Заблокируем кнопку и изменим текст на ней до появления окна that.textContent = "Ждите..."; that.setAttribute('disabled', ''); setTimeout(function() { document.getElementById('demoTimerPopupWrapper').style.display = 'flex'; startDemoTimer(15, 0); // Вернем кнопке начальное состояние that.textContent = "Старт"; that.removeAttribute('disabled'); }, 3000); }); // Функция счетчика function startDemoTimer(minutes, seconds) { // Функция setValueToTimerField будет устанавливать значения минут или секунд в соответствующие поля setValueToTimerField('demoTimerMinutes', minutes); setValueToTimerField('demoTimerSeconds', seconds); // Запустим счетчик и получим его идентификатор // Функция countDemoTime будет выполняться каждую секунду const counterId = setInterval(countDemoTime, 1000); // Сохраним id счетчика в качестве значения data-атрибута в HTML-элементе с идентификатором demoTimerCounter // Это нужно, чтобы в последствии иметь возможность остановить счетчик document.getElementById('demoTimerCounter').dataset.counterId = String(counterId); } // Вспомогательная функция для установки значений минут и секунд function setValueToTimerField(fieldId, value) { document.getElementById(fieldId).value = String(value).padStart(2, '0'); } // Функция, вызываемая каждую секунду function countDemoTime() { // Возьмем текущие значения минут и секунд let currentMinutes = document.getElementById('demoTimerMinutes').value; let currentSeconds = document.getElementById('demoTimerSeconds').value; // Если текущие значения минут и секунд равны нулям... if ((+currentMinutes === 0) && (+currentSeconds === 0)) { // ...заберем сохраненный id счетчика у элемента demoTimerCounter и передадим этот идентификатор функции clearInterval для остановки счетчика... clearInterval(+document.getElementById('demoTimerCounter').dataset.counterId); // ...отобразим сообщение об окончании акции... document.getElementById('demoTimerExpired').style.display = 'block'; // ...уберем кнопку для перехода на страницу с акцией... document.getElementById('demoTimerAction').style.display = 'none'; // ...закончим на этом работу счетчика return; } // Если секунды равны нулю, уменьшаем значение минут на единицу, а значение секунд устанавливаем в 59 // Это означает, что начинается отсчет следующей минуты в обратном порядке if (+currentSeconds === 0) { setValueToTimerField('demoTimerMinutes', --currentMinutes); setValueToTimerField('demoTimerSeconds', 59); } else { setValueToTimerField('demoTimerSeconds', --currentSeconds); } } // Остановим счетчик при нажатии на кнопку "Успеть" document.getElementById('demoTimerAction').addEventListener('click', function(event) { event.preventDefault(); clearInterval(+document.getElementById('demoTimerCounter').dataset.counterId); }); // При нажатии на крестик с правом верхнем углу блока, спрячем этот блок и остановим счетчик, чтобы при следующем открытии всплывающего окна не работало несколько таймеров document.getElementById('demoTimerClose').addEventListener('click', function() { document.getElementById('demoTimerPopupWrapper').style.display = 'none'; clearInterval(+document.getElementById('demoTimerCounter').dataset.counterId); });
Этот js-код можно переписать, используя возможности библиотеки jQuery:
jQuery(function($) { $('#startDemoTimer').click(function() { const that = $(this); that.text("Ждите..."); that.attr('disabled', true); setTimeout(function() { $('#demoTimerPopupWrapper').css('display', 'flex'); startDemoTimer(15, 0); that.text("Старт"); that.attr('disabled', false); }, 3000); }); function startDemoTimer(minutes, seconds) { setValueToTimerField('demoTimerMinutes', minutes); setValueToTimerField('demoTimerSeconds', seconds); const counterId = setInterval(countDemoTime, 1000); $('#demoTimerCounter').attr('data-counter-id', String(counterId)); } function setValueToTimerField(fieldId, value) { $('#' + fieldId).val(String(value).padStart(2, '0')); } function countDemoTime() { let currentMinutes = $('#demoTimerMinutes').val(); let currentSeconds = $('#demoTimerSeconds').val(); if ((+currentMinutes === 0) && (+currentSeconds === 0)) { clearInterval(+$('#demoTimerCounter').attr('data-counter-id')); $('#demoTimerExpired').css('display', 'block'); $('#demoTimerAction').css('display', 'none'); return; } if (+currentSeconds === 0) { setValueToTimerField('demoTimerMinutes', --currentMinutes); setValueToTimerField('demoTimerSeconds', 59); } else { setValueToTimerField('demoTimerSeconds', --currentSeconds); } } $('#demoTimerAction').click(function(event) { event.preventDefault(); clearInterval(+$('#demoTimerCounter').attr('data-counter-id')); }); $('#demoTimerClose').click(function() { $('#demoTimerPopupWrapper').css('display', 'none'); clearInterval(+$('#demoTimerCounter').attr('data-counter-id')); }); });
В итоге у нас получился ожидаемый рекламный блок. Результат можно увидеть, нажав на кнопку «Старт»:
Акция!
50% скидка на подписку на все курсы по программированию!
До конца осталось:
Мы запускаем наше всплывающее окно при нажатии на кнопку с помощью JavaScript-события click
. Изначально мы предположили, что этот блок будет появляться после загрузки страницы. Примеры, как этого достичь на нативном JavaScript и с помощью библиотеки jQuery, ниже :
// JavaScript document.addEventListener('DOMContentLoaded', function () { setTimeout(function() { document.getElementById('demoTimerPopupWrapper').style.display = 'flex'; startDemoTimer(15, 0); }, 3000); }); // jQuery $(document).ready(function() { setTimeout(function() { $('#demoTimerPopupWrapper').css('display', 'flex'); startDemoTimer(15, 0); }, 3000); });
После такого изменения блок отобразится через три секунды загрузки страницы.
Заготовка нашего таймера готова. Мы рассмотрели работу методов setTimeout
и setInterval
на реальном примере. Получилось ли у вас создать таймер на js? Поделитесь в комментариях.