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

В какой последовательности выполняются таски

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

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

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

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

В какой последовательности выполняются таски

Порядок выполнения задач в JavaScript — это фундаментальная концепция асинхронного программирования. JavaScript использует event loop для управления выполнением кода, и понимание этого процесса критично для написания правильного асинхронного кода.

Event Loop и три слоя очередей

Выполнение кода в JavaScript следует следующему порядку:

  1. Synchronous (синхронный) код — выполняется немедленно
  2. Microtasks (микротаски) — обрабатываются после синхронного кода
  3. Macrotasks (макротаски) — обрабатываются после очистки микротасков

Что входит в каждый уровень

Синхронный код:

console.log("1");
const x = 5 + 3;
console.log("2");
// Вывод: 1, 2 (в порядке их появления в коде)

Микротаски (выполняются раньше макротасков):

  • Promise.then(), Promise.catch(), Promise.finally()
  • async/await
  • queueMicrotask()
  • Observers (MutationObserver, IntersectionObserver)

Макротаски (отправляются в очередь после микротасков):

  • setTimeout()
  • setInterval()
  • setImmediate() (в Node.js)
  • requestAnimationFrame()
  • Обработчики событий (click, scroll и т.д.)
  • UI rendering

Пример полного цикла event loop

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

setTimeout(() => {
  console.log("setTimeout"); // 5. Макротаска
}, 0);

Promise.resolve()
  .then(() => {
    console.log("Promise 1"); // 2. Микротаска
  })
  .then(() => {
    console.log("Promise 2"); // 3. Микротаска
  });

queueMicrotask(() => {
  console.log("queueMicrotask"); // 4. Микротаска
});

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

// Вывод:
// Start
// End
// Promise 1
// Promise 2
// queueMicrotask
// setTimeout

Практический пример с async/await

async function example() {
  console.log("1"); // Синхронный
  
  await Promise.resolve();
  console.log("2"); // Микротаска (после await)
}

setTimeout(() => {
  console.log("3"); // Макротаска
}, 0);

example();

console.log("4"); // Синхронный

// Вывод:
// 1
// 4
// 2
// 3

Почему это важно

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

Оптимизация производительности — микротаски выполняются синхронно без перерывов, поэтому для批量 обновлений лучше использовать Promises вместо setTimeout.

Отладка асинхронного кода — понимание event loop помогает объяснить, почему код выполняется не в том порядке, в котором написан.

Сложный пример: стек вызовов и очереди

console.log("script start");

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

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

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

console.log("script end");

// Вывод:
// script start
// script end
// promise 1
// promise 2
// setTimeout 1
// promise in setTimeout
// setTimeout 2
// setTimeout in promise

Ключевые выводы

  • Event loop непрерывно проверяет стек вызовов и очереди
  • Микротаски всегда выполняются перед макротасками
  • await — это синтаксический сахар для .then(), оба работают одинаково
  • setTimeout(..., 0) не выполняется немедленно, а отправляется в очередь макротасок
  • Для высокоприоритетных операций используй Promises, для менее срочных — setTimeout

Понимание этого механизма — критически важно для работы с асинхронным JavaScript и избежания ошибок в production-коде.

В какой последовательности выполняются таски | PrepBro