Кратко
Microtask — задача с максимальным приоритетом. Все microtasks выполняются ПОСЛЕ текущего синхронного кода, НО ДО следующей макрозадачи. Promise.then, queueMicrotask, MutationObserver — microtasks. setTimeout, setInterval — macrotasks.
Подробно
Очереди задач:
- Call stack (синхронный код)
- Microtask queue (Promise.then, queueMicrotask)
- Macrotask queue (setTimeout, setInterval)
Порядок выполнения: // Задача 1: синхронный код console.log('1');
// Задача 2: microtask Promise.resolve().then(() => console.log('2'));
// Задача 3: microtask queueMicrotask(() => console.log('3'));
// Задача 4: macrotask setTimeout(() => console.log('4'), 0);
console.log('5');
// Вывод: 1, 5, 2, 3, 4
Важно: microtask queue очищается ПОЛНОСТЬЮ
console.log('start');
Promise.resolve().then(() => { console.log('micro1'); Promise.resolve().then(() => console.log('micro2')); });
setTimeout(() => console.log('macro'), 0); console.log('end');
// Вывод: start, end, micro1, micro2, macro // micro2 — тоже microtask, выполняется до macro!
MutationObserver callback — тоже microtask (JA11).
Где это важно:
- Порядок обновления UI
- Порядок вызова callback'ов
- Когда один Promise создаёт другой Promise
Ментальная модель
Microtask queue — как VIP-очередь. Синхронный код — текущий клиент (обслуживается сразу). Microtasks — VIP-клиенты (обслуживаются ВСЕ перед обычными). Macrotasks — обычные клиенты (обслуживаются по одному после VIP).
Примеры
**Самый простой:**
console.log('1');
Promise.resolve().then(() => console.log('2'));
setTimeout(() => console.log('3'), 0);
console.log('4');
// Вывод: 1, 4, 2, 3
// Синхронный → Microtask → MacrotaskБазовый порядок: sync → microtask → macrotask.
**Простой:**
Promise.resolve()
.then(() => {
console.log('micro1');
return Promise.resolve();
})
.then(() => console.log('micro2'));
Promise.resolve()
.then(() => console.log('micro3'));
setTimeout(() => console.log('macro'), 0);
// Вывод: micro1, micro3, micro2, macro
// micro3 выполняется ДО micro2,
// потому что micro1 уже завершилсяПорядок microtasks зависит от порядка разрешения Promises.
**Реальный пример:**
// Опасный паттерн: рекурсивные microtasks
function flood() {
Promise.resolve().then(flood);
}
flood(); // Microtask queue никогда не опустеет!
// setTimeout НЕ выполняется
// UI зависает
// Безопасный вариант
function safe() {
setTimeout(() => {
// Нагрузка распределяется по macrotasks
// UI остаётся отзывчивым
safe();
}, 0);
}Рекурсивные microtasks блокируют macrotasks и UI.
Частые ошибки
**Неправильно:** Думать, что microtasks и macrotasks выполняются параллельно
**Почему:** Они выполняются последовательно: сначала ВСЕ microtasks, потом одна macrotask.
**Правильно:** Microtask queue опустеет полностью → одна macrotask → снова microtasks.
**Неправильно:** Путать queueMicrotask и setTimeout(fn, 0)
**Почему:** queueMicrotask — microtask (приоритет). setTimeout — macrotask (после microtasks).
**Правильно:** queueMicrotask = VIP. setTimeout = обычный.
Важно запомнить
- Microtasks: Promise.then, queueMicrotask, MutationObserver
- Macrotasks: setTimeout, setInterval, I/O
- Microtask queue опустеет полностью перед следующей macrotask
- Рекурсивные microtasks блокируют macrotasks
- Порядок: sync → microtasks → macrotask
Связь
Назад: Вы знаете async/await (JA5) и Event Loop (DA11). Микрозадачи — внутренний механизм, стоящий за колбэками Promise.
Вперёд: Следующий урок (JV12) — конструктор и new — как создаются объекты.