Что такое setTimeout, для чего он нужен и как работает?

👨‍💻 Frontend Developer 🟠 Может встретиться 🎚️ Легкий
#JavaScript #Асинхронность #База JS

Краткий ответ

setTimeout — это метод в JavaScript, который позволяет выполнить функцию или фрагмент кода после указанной задержки в миллисекундах. Он не блокирует выполнение основного потока кода, а регистрирует таймер и продолжает работу. Это основной инструмент для создания асинхронных операций, таких как отложенные уведомления, анимации или выполнение задач без замораживания интерфейса. Для отмены таймера используется clearTimeout.


Что такое setTimeout

setTimeout — это встроенная функция в браузерах и Node.js, которая позволяет запланировать выполнение функции через определенное время. Она возвращает числовой идентификатор таймера, который можно использовать для его отмены.

Синтаксис

const timerId = setTimeout(callback, delay, ...args);
  • callback: Функция, которую нужно выполнить.
  • delay: Задержка в миллисекундах (1000 мс = 1 секунда). Если не указана, по умолчанию равна 0.
  • ...args: Дополнительные аргументы, которые будут переданы в callback при его вызове.

Как это работает: Цикл событий (Event Loop)

setTimeout не гарантирует, что функция выполнится ровно через указанное время. Он гарантирует, что она будет добавлена в очередь задач (callback queue) не раньше, чем через delay.

  1. Вызов setTimeout передает таймер в API браузера (Web APIs).
  2. Основной поток JavaScript продолжает выполняться без блокировки.
  3. Когда таймер истекает, callback помещается в очередь задач.
  4. Цикл событий (Event Loop) проверяет, пуст ли стек вызовов (call stack).
  5. Как только стек становится пустым, callback из очереди перемещается в стек и выполняется.

Именно поэтому setTimeout(fn, 0) не выполняется немедленно, а ставится в конец очереди, уступая дорогу текущему коду.


Примеры использования

1. Простая задержка

console.log("Привет!");
 
setTimeout(() => {
  console.log("Этот код выполнится через 2 секунды.");
}, 2000);
 
console.log("Этот код не будет ждать.");

Результат в консоли:

  1. “Привет!”
  2. “Этот код не будет ждать.”
  3. (через 2 секунды) “Этот код выполнится через 2 секунды.”

2. Передача аргументов в callback

function greet(name, phrase) {
  console.log(`${phrase}, ${name}!`);
}
 
setTimeout(greet, 1500, "Александр", "Добрый день");
// Выведет: "Добрый день, Александр!" через 1.5 секунды

3. Отмена таймера с помощью clearTimeout

Если вы хотите отменить запланированное выполнение, используйте clearTimeout, передав ему timerId.

const timerId = setTimeout(() => {
  console.log("Это сообщение никогда не появится.");
}, 5000);
 
console.log(`Таймер с ID ${timerId} запущен.`);
 
// Отменяем таймер через 2 секунды
setTimeout(() => {
  clearTimeout(timerId);
  console.log(`Таймер с ID ${timerId} отменен.`);
}, 2000);

Задачи для практики

Задача 1

// В каком порядке числа появятся в консоли?
console.log(1);
 
setTimeout(() => console.log(2), 1000);
setTimeout(() => console.log(3), 0);
 
console.log(4);
Ответ **Порядок: `1`, `4`, `3`, `2`**

Объяснение:

  1. console.log(1) выполняется синхронно.
  2. setTimeout с задержкой 1000 мс регистрирует таймер.
  3. setTimeout с задержкой 0 мс помещает console.log(3) в очередь задач.
  4. console.log(4) выполняется синхронно.
  5. После завершения синхронного кода цикл событий выполняет задачи из очереди, начиная с console.log(3).
  6. Через 1 секунду выполняется console.log(2).

Задача 2

// Напишите функцию, которая выводит в консоль числа от 1 до 5
// с интервалом в 1 секунду между каждым числом.
 
function printNumbers() {
  // Ваш код
}
 
printNumbers();
Ответ
function printNumbers() {
  for (let i = 1; i <= 5; i++) {
    setTimeout(() => {
      console.log(i);
    }, i * 1000);
  }
}

Объяснение: Мы используем let для создания блочной области видимости для i. Каждая итерация цикла создает новую переменную i, которую setTimeout “запоминает”. Задержка i * 1000 обеспечивает последовательный вывод чисел каждую секунду.