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

Что попадает к Микрозадачам кроме Promise?

1.0 Junior🔥 251 комментариев
#JavaScript Core

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

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

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

Микрозадачи в JavaScript: не только Promise

В современном JavaScript Event Loop управляет выполнением кода, используя очереди задач. Микрозадачи (microtasks) — это особый тип задач с высшим приоритетом, которые выполняются после завершения текущей синхронной задачи, но до рендеринга и выполнения макрозадач. Хотя Promise действительно являются самым распространённым источником микрозадач, ими список не ограничивается.

Основные источники микрозадач

1. Promise

Методы Promise создают микрозадачи для своих обработчиков:

  • Promise.then() / Promise.catch() / Promise.finally()
  • Promise.resolve() / Promise.reject() (при цепочке вызовов)
  • async/await (синтаксический сахар над Promise)
Promise.resolve().then(() => console.log('Микрозадача от Promise'));

2. MutationObserver

API для наблюдения за изменениями в DOM. Коллбэки MutationObserver выполняются как микрозадачи.

const observer = new MutationObserver(() => {
    console.log('Микрозадача от MutationObserver');
});
observer.observe(document.body, { childList: true });

3. queueMicrotask()

Специальный API, добавленный для явного помещения функций в очередь микрозадач.

queueMicrotask(() => {
    console.log('Явно добавленная микрозадача');
});

4. process.nextTick() (только Node.js)

В среде Node.js process.nextTick() создаёт микрозадачи с даже более высоким приоритетом, чем Promise.

process.nextTick(() => {
    console.log('Микрозадача в Node.js');
});

5. Object.observe() (устаревший)

Устаревший API, который также использовал микрозадачи для своих коллбэков.

Практическое значение понимания микрозадач

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

Микрозадачи образуют очередь (FIFO), которая опустошается полностью перед переходом к следующей макрозадаче:

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

setTimeout(() => console.log('6. Макрозадача (setTimeout)'), 0);

Promise.resolve()
    .then(() => {
        console.log('3. Микрозадача 1 от Promise');
        return 'result';
    })
    .then((value) => {
        console.log('4. Микрозадача 2 от Promise:', value);
    });

queueMicrotask(() => console.log('5. Микрозадача от queueMicrotask'));

console.log('2. Конец синхронного кода');

Важные последствия для производительности

  1. Рекурсивные микрозадачи могут заблокировать Event Loop

    function recursiveMicrotask() {
        Promise.resolve().then(recursiveMicrotask);
    }
    // Вызов заблокирует основной поток навсегда!
    
  2. Порядок рендеринга: браузер рендерит изменения только после полного опустошения очереди микрозадач.

Отличия от макрозадач

МикрозадачиМакрозадачи
Promise, queueMicrotasksetTimeout, setInterval
MutationObserversetImmediate (Node.js)
Высший приоритетНизший приоритет
Выполняются между макрозадачамиВыполняются в отдельных тиках Event Loop

Паттерны использования

Пакетирование операций

let isPending = false;
let queue = [];

function processQueue() {
    if (isPending) return;
    
    isPending = true;
    queueMicrotask(() => {
        // Обработка всех накопленных операций
        while (queue.length) {
            const task = queue.shift();
            task();
        }
        isPending = false;
    });
}

Избегание "залипания" UI

// Плохо - блокирует рендеринг
function processData(data) {
    data.forEach(item => heavyCalculation(item));
}

// Хорошо - позволяет браузеру рендерить
async function processData(data) {
    for (const item of data) {
        await Promise.resolve(); // Разрешает рендеринг между операциями
        heavyCalculation(item);
    }
}

Особенности браузеров и Node.js

В браузерах порядок обычно такой:

  1. Выполнение синхронного кода
  2. Опустошение очереди микрозадач
  3. Рендеринг (при необходимости)
  4. Выполнение одной макрозадачи
  5. Повтор цикла

В Node.js ситуация сложнее из-за дополнительных фаз Event Loop (timers, poll, check и т.д.), но принцип приоритета микрозадач сохраняется.

Заключение

Понимание микрозадач выходит за рамки работы с Promise и является фундаментальным аспектом асинхронного программирования в JavaScript. Правильное использование различных источников микрозадач позволяет оптимизировать производительность, управлять приоритетом операций и создавать отзывчивые интерфейсы. Современные API вроде queueMicrotask() дают разработчикам прямой контроль над этим механизмом, что особенно полезно при реализации сложных асинхронных паттернов и библиотек.

Что попадает к Микрозадачам кроме Promise? | PrepBro