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

Выполняются ли сначала все micro tasks а затем macro tasks

2.8 Senior🔥 201 комментариев
#JavaScript Core#Браузер и сетевые технологии

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

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

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

Порядок выполнения Microtasks и Macrotasks в JavaScript

Да, в JavaScript существует чётко определённый порядок выполнения асинхронных операций. Все microtasks выполняются перед macrotasks. Это важнейшая концепция для понимания event loop.

Event Loop и его цикл

Event loop работает следующим образом:

  1. Выполняется код из call stack (синхронный код)
  2. Когда call stack пуст, выполняются ВСЕ microtasks из microtask queue
  3. После очистки всех microtasks выполняется ОДИН macrotask
  4. После macrotask снова проверяются microtasks
  5. Цикл повторяется

Это означает, что microtasks всегда имеют приоритет над macrotasks.

Категории задач

Microtasks (микротаски):

  • Promise callbacks (.then(), .catch(), .finally())
  • async/await (работает как Promise)
  • MutationObserver
  • queueMicrotask()

Macrotasks (макротаски):

  • setTimeout()
  • setInterval()
  • setImmediate() (Node.js)
  • requestAnimationFrame()
  • I/O операции
  • UI rendering
  • обработка событий (click, scroll)

Пример выполнения

console.log("1. Начало");

setTimeout(() => {
  console.log("2. setTimeout (macrotask)");
}, 0);

Promise.resolve()
  .then(() => {
    console.log("3. Promise.then (microtask)");
  });

queueMicrotask(() => {
  console.log("4. queueMicrotask (microtask)");
});

console.log("5. Конец");

// Результат:
// 1. Начало
// 5. Конец
// 3. Promise.then (microtask)
// 4. queueMicrotask (microtask)
// 2. setTimeout (macrotask)

Более сложный пример

console.log("Start");

setTimeout(() => {
  console.log("Timeout 1");
  Promise.resolve().then(() => {
    console.log("Promise в Timeout 1");
  });
}, 0);

Promise.resolve()
  .then(() => {
    console.log("Promise 1");
    setTimeout(() => {
      console.log("Timeout в Promise 1");
    }, 0);
  })
  .then(() => {
    console.log("Promise 2");
  });

console.log("End");

// Результат:
// Start
// End
// Promise 1
// Promise 2
// Timeout 1
// Promise в Timeout 1
// Timeout в Promise 1

Практическое значение

Это поведение критично для:

  • Обработки асинхронного кода: понимание очерёдности помогает избежать race conditions
  • Оптимизации производительности: microtasks выполняются раньше перерисовки, а macrotasks могут быть после
  • Отладки: неожиданный порядок выполнения часто связан с неправильным пониманием event loop

Визуализация цикла

// 1. Синхронный код (call stack)
console.log("Sync");

// 2. После того как call stack пуст
// начинают выполняться microtasks по очереди
Promise.resolve().then(() => console.log("Micro 1"));
Promise.resolve().then(() => console.log("Micro 2"));

// 3. После всех microtasks выполняется один macrotask
setTimeout(() => console.log("Macro 1"), 0);
setTimeout(() => console.log("Macro 2"), 0);

// 4. После macrotask снова проверяются microtasks
// если они есть

Понимание этого порядка — основа для работы с асинхронным JavaScript и правильной организации кода в современных приложениях.

Выполняются ли сначала все micro tasks а затем macro tasks | PrepBro