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

Приведи примеры создания макрозадач

1.0 Junior🔥 241 комментариев
#State Management#TypeScript

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

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

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

Создание макрозадач в JavaScript: полный обзор

Макрозадачи (macrotasks) — это задачи, которые выполняются в основном потоке выполнения JavaScript после завершения текущего синхронного кода и перед следующей итерацией цикла событий. Вот основные способы их создания с подробными примерами.

1. setTimeout() и setInterval() — классические макрозадачи

Наиболее распространённые API для создания макрозадач. Они помещают колбэк в очередь макрозадач после указанной задержки.

// Пример с setTimeout
console.log('Старт синхронного кода');

setTimeout(() => {
  console.log('Макрозадача из setTimeout выполнилась');
}, 1000);

setTimeout(() => {
  console.log('Макрозадача с нулевой задержкой');
}, 0);

console.log('Конец синхронного кода');

// Вывод:
// Старт синхронного кода
// Конец синхронного кода
// Макрозадача с нулевой задержкой
// Макрозадача из setTimeout выполнилась
// Пример с setInterval
let counter = 0;
const intervalId = setInterval(() => {
  counter++;
  console.log(`Интервал выполнен ${counter} раз`);
  
  if (counter >= 3) {
    clearInterval(intervalId);
    console.log('Интервал остановлен');
  }
}, 500);

// setInterval создаёт новую макрозадачу каждые 500 мс

2. setImmediate() — Node.js специфика

Доступен только в среде Node.js, планирует выполнение колбэка сразу после завершения текущего цикла событий.

// Пример в Node.js
console.log('Начало выполнения');

setImmediate(() => {
  console.log('setImmediate выполнен');
});

setTimeout(() => {
  console.log('setTimeout с нулевой задержкой');
}, 0);

console.log('Конец синхронного кода');

// Возможный вывод:
// Начало выполнения
// Конец синхронного кода
// setTimeout с нулевой задержкой
// setImmediate выполнен
// Порядок может варьироваться в зависимости от фазы цикла событий

3. Обработчики событий — пользовательские взаимодействия

Любые события DOM (клики, нажатия клавиш, загрузка ресурсов) создают макрозадачи.

// Пример с обработчиком клика
document.getElementById('myButton').addEventListener('click', () => {
  console.log('Обработчик клика — это макрозадача');
});

// События загрузки
window.addEventListener('load', () => {
  console.log('Страница полностью загружена — макрозадача');
});

// События таймера requestAnimationFrame (хотя имеет особый статус)
requestAnimationFrame(() => {
  console.log('requestAnimationFrame — выполняется перед ререндером');
});

4. MessageChannel — продвинутое создание макрозадач

Позволяет явно создать макрозадачу с более высоким приоритетом, чем setTimeout(..., 0).

// Создание канала для передачи сообщений
const channel = new MessageChannel();
const port = channel.port2;

channel.port1.onmessage = () => {
  console.log('Макрозадача через MessageChannel выполнена');
};

console.log('Перед отправкой сообщения');
port.postMessage(null);
console.log('После отправки сообщения');

// Вывод:
// Перед отправкой сообщения
// После отправки сообщения
// Макрозадача через MessageChannel выполнена

5. Динамический импорт модулей — import()

Динамический импорт также создаёт макрозадачу для загрузки и выполнения модуля.

// Пример динамического импорта
console.log('Начинаем загрузку модуля');

import('./myModule.js')
  .then(module => {
    console.log('Модуль загружен — макрозадача выполнена');
    module.someFunction();
  })
  .catch(error => {
    console.error('Ошибка загрузки модуля:', error);
  });

console.log('Синхронный код продолжает выполняться');

6. queueMicrotask() vs макрозадачи — важное отличие

Для контраста покажу разницу между микрозадачами и макрозадачами:

console.log('Скрипт начался');

// Макрозадача
setTimeout(() => {
  console.log('Макрозадача из setTimeout');
}, 0);

// Микрозадача
Promise.resolve().then(() => {
  console.log('Микрозадача из Promise');
});

// Ещё одна микрозадача
queueMicrotask(() => {
  console.log('Микрозадача из queueMicrotask');
});

console.log('Скрипт завершился');

// Вывод:
// Скрипт начался
// Скрипт завершился
// Микрозадача из Promise
// Микрозадача из queueMicrotask
// Макрозадача из setTimeout

Ключевые особенности макрозадач:

  • Выполняются после микрозадач — приоритет микрозадач выше
  • Не блокируют основной поток — браузер может рендерить между макрозадачами
  • Могут быть отмененыclearTimeout(), clearInterval()
  • Имеют минимальную задержку — обычно 4-10 мс в браузерах даже при setTimeout(..., 0)
  • Подвержены throttle — в неактивных вкладках таймеры замедляются

Практический пример с анимацией:

// Поэтапная анимация через макрозадачи
function animateElement(element, duration) {
  const startTime = Date.now();
  
  function updateAnimation() {
    const elapsed = Date.now() - startTime;
    const progress = Math.min(elapsed / duration, 1);
    
    // Обновляем стиль элемента
    element.style.transform = `translateX(${progress * 200}px)`;
    
    if (progress < 1) {
      // Создаём новую макрозадачу для следующего кадра
      setTimeout(updateAnimation, 16); // ~60 FPS
    }
  }
  
  // Запускаем первую макрозадачу
  setTimeout(updateAnimation, 0);
}

// Использование
const box = document.getElementById('animatedBox');
animateElement(box, 1000); // Анимация на 1 секунду

Понимание работы макрозадач критически важно для написания производительного и отзывчивого JavaScript-кода, особенно при работе с анимациями, обработкой пользовательского ввода и управлением состоянием приложения.

Приведи примеры создания макрозадач | PrepBro