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. Их простота и гибкость делают их незаменимыми в задачах от прототипирования до продвинутых сценариев, таких как дебаунсинг или интеграция с современными фреймворками. Понимание их места в цикле событий и ограничений позволяет эффективно использовать их в профессиональной разработке.

Полезные статьи — по почте

Подпишитесь на редакторскую рассылку о фронтенде, новых CSS-штучках и всём, что пригодится разработчику.

Присылаем одно письмо в неделю. Без спама и нейросетей.

Нажатие на кнопку — согласие на подписку


«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.

ТелеграмПодкастБесплатные учебники