Что такое макро и микро задачи в JS?angular-13

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

В JavaScript асинхронные операции делятся на два типа задач, которые обрабатываются Event Loop по разным правилам:

1. Макротаски

  • Выполняются после текущего синхронного кода и всех микротасок
  • Помещаются в Task Queue (Callback Queue)
  • Типичные примеры:
    • setTimeout()
    • setInterval()
    • setImmediate() (Node.js)
    • События DOM (click, load и др.)
    • I/O операции
    • UI rendering

2. Микротаски

  • Выполняются сразу после текущего синхронного кода, но перед макротасками
  • Помещаются в Microtask Queue
  • Типичные примеры:
    • Promise.then()/catch()/finally()
    • queueMicrotask()
    • MutationObserver
    • process.nextTick() (Node.js)

Детальный механизм работы

Event Loop обрабатывает задачи в строгом порядке:

  1. Выполняет весь синхронный код (Call Stack)
  2. Обрабатывает все доступные микротаски
  3. Выполняет одну макротаску
  4. Повторяет цикл

Наглядный пример:

console.log('Script start');

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

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

console.log('Script end');

Вывод:

  1. Script start
  2. Script end
  3. Promise 1
  4. Promise 2
  5. setTimeout

Особенности в Angular

Angular использует зону (NgZone) для отслеживания асинхронных операций и запуска Change Detection:

  1. Микротаски:

    • Promise-обработчики
    • Вызовы async/await
    • Вызывают Change Detection сразу после выполнения
  2. Макротаски:

    • setTimeout/setInterval
    • DOM события
    • Также вызывают Change Detection

Пример Angular-специфичного поведения:

ngOnInit() {
  setTimeout(() => {
    this.value = 'Macrotask'; // Вызовет Change Detection
  }, 0);

  Promise.resolve().then(() => {
    this.value = 'Microtask'; // Вызовет Change Detection раньше
  });
}

Опасные ситуации

  1. Рекурсия микротасок:
function recursiveMicrotask() {
  Promise.resolve().then(recursiveMicrotask);
}

Блокирует основной поток, так как Event Loop не перейдет к макротаскам.

  1. Долгие вычисления в микротасках:
    • Могут задержать критически важные макротаски (например, анимации)

Практические рекомендации

  1. Для фоновых задач используйте макротаски (setTimeout)
  2. Для высокоприоритетных операций - микротаски (queueMicrotask)
  3. В Angular для оптимизации:
    • NgZone.runOutsideAngular() + requestAnimationFrame() для анимаций
    • ChangeDetectorRef.detectChanges() для ручного управления

Резюмируем

  1. Микротаски:

    • Более высокий приоритет
    • Выполняются до рендеринга и макротасок
    • Используются для Promise, MutationObserver
  2. Макротаски:

    • Более низкий приоритет
    • Включают таймеры, события, I/O
    • Выполняются после всех микротасок
  3. В Angular:

    • Оба типа задач запускают Change Detection
    • Микротаски могут привести к частым проверкам
    • Оптимизация требует понимания их работы

Понимание разницы критически важно для:

  • Оптимального управления Change Detection
  • Предотвращения проблем с производительностью
  • Создания отзывчивых интерфейсов