Чем отличаются микротаски и макротаски?nodejs-23

Основные понятия

Микротаски

  • Выполняются сразу после текущей синхронной задачи
  • Имеют высший приоритет в Event Loop
  • Примеры:
    • Promise callbacks (then/catch/finally)
    • queueMicrotask()
    • process.nextTick() (Node.js specific, но похоже)

Макротаски

  • Выполняются в следующих итерациях Event Loop
  • Имеют более низкий приоритет
  • Примеры:
    • setTimeout/setInterval
    • setImmediate (Node.js)
    • I/O операции
    • UI rendering (в браузере)

Ключевые различия

Характеристика Микротаски Макротаски
ПриоритетВысшийНизкий
ОчередьСобственная очередьОчередь Event Loop
Когда выполняютсяМежду макротаскамиВ следующих тиках Event Loop
ПримерыPromise, process.nextTicksetTimeout, setImmediate

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

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

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

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

queueMicrotask(() => console.log('queueMicrotask'));

console.log('Синхронный код 2');

Вывод:

  1. Синхронный код 1
  2. Синхронный код 2
  3. Promise 1
  4. queueMicrotask
  5. Promise 2
  6. setTimeout

Глубокое объяснение

1. Механизм выполнения в Event Loop

Микротаски:

  • Выполняются до перехода к следующей фазе Event Loop
  • Обрабатываются до следующего макротаска
  • Очередь должна быть полностью очищена перед продолжением

Макротаски:

  • Выполняются в соответствующих фазах Event Loop
  • Одна макротаска за одну итерацию цикла (в общем случае)

2. Особенности Node.js

process.nextTick - особый случай:

  • Технически не микротаска, но ведет себя похоже
  • Имеет даже более высокий приоритет, чем Promise
Promise.resolve().then(() => console.log('Promise'));
process.nextTick(() => console.log('nextTick'));
// nextTick выполнится первым

3. Проблемы и подводные камни

Рекурсивные микротаски:

function recursiveMicrotask() {
  Promise.resolve().then(recursiveMicrotask);
}
// Полностью заблокирует Event Loop

Разница между браузером и Node.js:

  • Браузеры обычно имеют одну очередь микротаск
  • Node.js разделяет process.nextTick и Promise очереди

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

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

    • Микротаски всегда между синхронным кодом и макротасками
    • Важно для согласованности состояния приложения
  2. Производительность:

    • Избыток микротаск может задержать I/O операции
    • Макротаски лучше для тяжелых задач
  3. Отладка:

    • Понимание порядка помогает находить race conditions

Резюмируем

  1. Приоритет выполнения: Микротаски > Макротаски
  2. Использование:
    • Микротаски - для срочных асинхронных операций
    • Макротаски - для менее критичных задач
  3. Главное правило: Event Loop обрабатывает все микротаски перед переходом к следующей макротаске
  4. Особенности Node.js:
    • process.nextTick имеет наивысший приоритет
    • Отдельные очереди для разных типов задач

Понимание этих различий критично для написания корректного асинхронного кода и предотвращения тонких ошибок.