JavaScript

Чем микрозадачи отличаются от макрозадач?

Микрозадачи и макрозадачи

Макрозадачи (Macrotasks)

Каждый «тик» event loop - это одна макрозадача. После неё браузер может отрисовать кадр.

Источники макрозадач: setTimeout, setInterval, setImmediate (Node.js), I/O-события, обработчики UI-событий.

Микрозадачи (Microtasks)

Выполняются сразу после текущей задачи (или текущего синхронного кода), до следующей макрозадачи - и до рендера.

Источники микрозадач: Promise.then/catch/finally, queueMicrotask(), MutationObserver.

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

console.log("1 - sync")

setTimeout(() => console.log("2 - macro"), 0)

Promise.resolve()
  .then(() => console.log("3 - micro"))
  .then(() => console.log("4 - micro"))

queueMicrotask(() => console.log("5 - micro"))

console.log("6 - sync")

// Вывод: 1, 6, 3, 5, 4, 2

Почему 3, 5, 4 - все до 2?

Перед тем как взять следующую макрозадачу (setTimeout), event loop полностью опустошает очередь микрозадач. Причём если микрозадача порождает новую микрозадачу - та тоже выполняется до макрозадачи.

Важный кейс

// Бесконечная рекурсия микрозадач заморозит браузер!
function infinite() {
  Promise.resolve().then(infinite)
}
infinite()  // браузер не отрисует ни одного кадра

Источники