Таймеры в JS с setTimeout и clearTimeout
- 6 сентября 2025
setTimeout — это метод, предоставляемый API браузеров и Node.js, который позволяет выполнять код с заданной задержкой. Он принимает функцию (коллбэк), время задержки в миллисекундах и, опционально, аргуtimes для передачи в функцию. Для отмены выполнения используется clearTimeout.
setTimeout и setInterval были введены в первых версиях JavaScript (ECMAScript 1, 1997) как часть API WindowOrWorkerGlobalScope. Эти методы интегрированы в цикл событий (event loop), который управляет асинхронным выполнением в JavaScript. Несмотря на появление современных инструментов, таких как Promises и async/await, setTimeout остаётся востребованным благодаря своей простоте и универсальности.
const timerId = setTimeout(() => {
console.log('Сообщение появится через 2 секунды');
}, 2000);
// Отмена выполнения
clearTimeout(timerId);
Здесь setTimeout возвращает числовой идентификатор таймера (timerId), который используется в clearTimeout. В Node.js возвращается объект Timeout.
Важные особенности
- Задержка не гарантирована: Время выполнения зависит от загруженности цикла событий. Если браузер занят другими задачами, выполнение может произойти позже указанного времени.
- Минимальная задержка: В современных браузерах минимальная задержка в активных вкладках может быть около 1 мс, но в неактивных вкладках она увеличивается (например, до 1000 мс).
- Передача строки: Передача строки кода вместо функции обрабатывается через
eval, что является устаревшей и небезопасной практикой. Всегда используйте функции. - Макрозадачи:
setTimeoutрегистрирует макрозадачу в цикле событий, в отличие отPromises, которые используют микрозадачи, выполняемые с более высоким приоритетом.
Пример с аргументами
Коллбэку в setTimeout можно передать параметры:
function greet(name) {
console.log(`Привет, ${name}!`);
}
setTimeout(greet, 1500, 'Алексей');
// Через 1.5 секунды в консоль выведется: "Привет, Алексей!"
Рекурсивный setTimeout
setTimeout часто используется вместо setInterval для точного управления интервалами между вызовами:
let counter = 0;
function tick() {
if (counter >= 5) return; // Остановка после 5 итераций
console.log('Тик');
counter++;
setTimeout(tick, 1000);
}
setTimeout(tick, 1000);
// Каждую секунду будет появляться сообщение "Тик" (5 раз)
В отличие от setInterval, рекурсивный setTimeout начинает новый таймер только после завершения предыдущего вызова, что предотвращает накопление задержек.
Применение на практике
setTimeout используется в следующих сценариях:
- Создание отложенных анимаций (например, в паре с
requestAnimationFrame). - Эмуляция асинхронных операций, таких как загрузка данных.
- Реализация дебаунсинга для обработки событий, например, ввода текста в поисковой строке.
- Управление микрозадачами через
setTimeout(fn, 0)для отложенного выполнения кода после текущего стека вызовов.
const input = document.querySelector('input');
let timeoutId = null;
input.addEventListener('input', () => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
console.log('Запрос отправлен:', input.value);
}, 500);
});
// Запрос отправится, если пользователь не вводит текст в течение 0.5 секунды
Ограничения и особенности
clearTimeoutбезопасно игнорирует несуществующие идентификаторы таймеров.- В Node.js
setTimeoutвозвращает объектTimeout, который можно использовать для дополнительных операций, таких какtimeout.ref()илиtimeout.unref(). - Для анимаций предпочтительнее использовать
requestAnimationFrame, так как оно синхронизировано с частотой обновления экрана.
Заключение
setTimeout и clearTimeout — проверенные временем инструменты для работы с асинхронностью в JavaScript. Их простота и гибкость делают их незаменимыми в задачах от прототипирования до продвинутых сценариев, таких как дебаунсинг или интеграция с современными фреймворками. Понимание их места в цикле событий и ограничений позволяет эффективно использовать их в профессиональной разработке.
«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.