← Назад к вопросам

Зачем нужен setTimeout?

2.0 Middle🔥 171 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Зачем нужен setTimeout

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

Базовый синтаксис

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

console.log('Это выполнится первым');
// Вывод:
// Это выполнится первым
// Это выполнится через 2 секунды

setTimeout возвращает ID таймера, который можно использовать для отмены:

const timerId = setTimeout(() => {
  console.log('Не выполнится');
}, 1000);

clearTimeout(timerId); // Отменяем таймер

Основные практические применения

1. Асинхронное выполнение кода (микротаски и макротаски)

setTimeout отправляет функцию в макротаску (macrotask queue), что позволяет браузеру обновить интерфейс или обработать другие события:

console.log('1');

Promise.resolve().then(() => console.log('2'));

setTimeout(() => console.log('3'), 0);

console.log('4');

// Вывод: 1 4 2 3
// Так как Promise — микротаска (выполняется раньше), setTimeout — макротаска

2. Дебаунсинг (debouncing)

Отложить выполнение функции до того, как пользователь перестанет что-то делать:

function debounce(fn, delay) {
  let timerId;
  return function(...args) {
    clearTimeout(timerId);
    timerId = setTimeout(() => fn(...args), delay);
  };
}

const handleSearch = debounce((query) => {
  console.log('Поиск:', query);
}, 300);

input.addEventListener('input', (e) => handleSearch(e.target.value));
// API запрос сделается только если пользователь 300ms ничего не вводит

3. Throttling (троттлинг)

Ограничить частоту вызовов функции:

function throttle(fn, delay) {
  let lastCall = 0;
  return function(...args) {
    const now = Date.now();
    if (now - lastCall >= delay) {
      fn(...args);
      lastCall = now;
    }
  };
}

const handleScroll = throttle(() => {
  console.log('Scroll event');
}, 1000);

window.addEventListener('scroll', handleScroll);
// Функция вызовется максимум раз в секунду

4. Отдача контроля браузеру (Yield to Main)

Длинные вычисления могут заморозить интерфейс. setTimeout позволяет отдать контроль браузеру для обновления UI:

function processLargeDataset(data) {
  let index = 0;

  function processChunk() {
    const chunk = data.slice(index, index + 100);
    
    // Обрабатываем небольшую часть
    chunk.forEach(item => {
      // Тяжёлые вычисления
    });

    index += 100;

    if (index < data.length) {
      // Отдаём контроль браузеру
      setTimeout(processChunk, 0);
    }
  }

  processChunk();
}

5. Отложенные UI обновления

Некоторые обновления нужно сделать после того, как DOM отрендерился:

function showModal() {
  const modal = document.createElement('div');
  document.body.appendChild(modal);

  // CSS transition или анимация сработает, если применить класс
  // после того, как элемент попал в DOM
  setTimeout(() => {
    modal.classList.add('show');
  }, 0);
}

setTimeout vs requestAnimationFrame

setTimeout — для общих асинхронных задач, может выполниться в любой момент.

requestAnimationFrame — лучше для анимаций, потому что синхронизируется с кадром браузера (60fps):

// Не оптимально для анимации
setTimeout(() => {
  element.style.left = left + 'px';
}, 1000 / 60); // Может не совпасть с кадром

// Правильно для анимации
function animate(time) {
  element.style.left = left + 'px';
  requestAnimationFrame(animate);
}
requestAnimationFrame(animate);

setTimeout vs Promise

setTimeout(() => console.log('setTimeout'), 0);
Promise.resolve().then(() => console.log('Promise'));

// Promise выполнится первым, потому что это микротаска
// Вывод: Promise, setTimeout

Для асинхронного кода лучше использовать Promise, потому что:

  • Микротаски выполняются быстрее
  • Можно цепить .then() для последовательного выполнения
  • Лучше для обработки ошибок

Проблемы setTimeout и как их избежать

  1. Memory Leak — забыли очистить таймер

    class Component {
      mount() {
        this.timerId = setTimeout(() => this.update(), 1000);
      }
      unmount() {
        clearTimeout(this.timerId); // ВАЖНО!
      }
    }
    
  2. Race conditions — несколько таймеров могут конфликтовать

    let timerId;
    function cancel() {
      clearTimeout(timerId);
    }
    
  3. Точность — setTimeout не гарантирует точное время выполнения, может быть задержка

Резюме

setTimeout — это критически важный инструмент для:

  • Асинхронного выполнения кода
  • Дебаунсинга и троттлинга (оптимизация обработчиков событий)
  • Отдачи контроля браузеру при длинных вычислениях
  • Отложенных UI обновлений

Знание микротаск и макротаск очереди, а также понимание, когда использовать setTimeout vs Promise vs requestAnimationFrame — это основа асинхронного JavaScript.