Микрозадачи и промисы
Узнайте, почему обратные вызовы промисов выполняются первыми.
«Микрозадачи и промисы» — бесплатный урок JavaScript Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения JavaScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс JavaScript Academy содержит 4 уроков всего.
Что такое микрозадача?
Микрозадача — это отложенная задача с высоким приоритетом. Обратные вызовы промисов (.then, .catch, .finally) и queueMicrotask ставят микрозадачи в очередь.
Главное правило: после каждого синхронного выполнения все микрозадачи обрабатываются до любой макрозадачи.
Обратные вызовы промисов выполняются отложенно
Даже уже разрешённый промис ставит свой обратный вызов .then в очередь микрозадач. Он не выполняется синхронно.
console.log('start');
Promise.resolve().then(() => console.log('promise then'));
console.log('end');Микрозадачи опережают макрозадачи
Это самое важное правило порядка выполнения. Обратный вызов промиса выполняется до обратного вызова setTimeout, даже если таймер был поставлен в очередь первым.
setTimeout(() => console.log('timeout (macro)'), 0);
Promise.resolve().then(() => console.log('promise (micro)'));
console.log('sync');Очередь микрозадач обрабатывается полностью
Цикл обработки событий опустошает всю очередь микрозадач, прежде чем перейти к следующей макрозадаче. Несколько обратных вызовов промисов выполняются подряд в рамках этой обработки.
setTimeout(() => console.log('macro'), 0);
Promise.resolve().then(() => console.log('micro 1'));
Promise.resolve().then(() => console.log('micro 2'));
console.log('sync');Цепочки промисов
Каждый .then в цепочке ставит новую микрозадачу в очередь, когда предыдущая задача завершается. При этом все они выполняются до любого ожидающего таймера.
setTimeout(() => console.log('timeout'), 0);
Promise.resolve()
.then(() => console.log('then 1'))
.then(() => console.log('then 2'))
.then(() => console.log('then 3'));
console.log('sync');Микрозадачи, поставленные во время обработки очереди
Если микрозадача ставит в очередь другую микрозадачу, новая микрозадача также выполняется в рамках той же обработки очереди, до любой макрозадачи. Очередь продолжает опустошаться, пока действительно не станет пустой.
Promise.resolve().then(() => {
console.log('micro A');
Promise.resolve().then(() => console.log('micro B (added later)'));
});
setTimeout(() => console.log('macro'), 0);
console.log('sync');Разрешённые значения передаются дальше
Значение, возвращённое обработчиком .then, становится входным значением для следующего обработчика в цепочке — всё это выполняется через микрозадачи.
Promise.resolve(2)
.then(n => n * 3)
.then(n => n + 1)
.then(n => console.log('result', n));
console.log('sync first');async/await использует микрозадачи
Код после await возобновляет выполнение как микрозадача. Поэтому продолжение после ожидания выполняется до таймера, поставленного в очередь раньше.
async function run() {
console.log('a');
await null;
console.log('c (after await)');
}
setTimeout(() => console.log('d (timeout)'), 0);
run();
console.log('b');Общий пример порядка выполнения
Объединим всё вместе. Предскажите порядок: сначала синхронное выполнение, затем все микрозадачи, затем макрозадача.
console.log('1 sync');
setTimeout(() => console.log('5 timeout'), 0);
Promise.resolve().then(() => console.log('3 promise'));
Promise.resolve().then(() => console.log('4 promise'));
console.log('2 sync');Почему истощение микрозадач опасно
Поскольку микрозадачи всегда выполняются до макрозадач, микрозадача, которая бесконечно ставит в очередь новые микрозадачи, может заблокировать таймеры и отрисовку. Цепочки микрозадач должны быть конечными.
let n = 0;
function loop() {
if (n++ < 3) {
console.log('micro ' + n);
Promise.resolve().then(loop);
}
}
setTimeout(() => console.log('macro after micros'), 0);
loop();Почему этот порядок важен
Знание о том, что микрозадачи выполняются до макрозадач, объясняет, почему результаты промисов появляются до обратных вызовов таймеров и почему возникают ошибки в порядке выполнения. Правило простое: синхронное выполнение, затем обработка всех микрозадач, затем одна макрозадача — и повторить.
console.log('A');
Promise.resolve().then(() => console.log('B'));
setTimeout(() => console.log('D'), 0);
console.log('C');Быстрая проверка
Обратный вызов .then промиса и setTimeout(fn, 0) ожидают выполнения. Что выполнится первым?
Итоги: микрозадачи и промисы
Вы усвоили правило приоритета:
- Микрозадачи создаются промисами и
queueMicrotask. - Вся очередь микрозадач обрабатывается до любой макрозадачи.
- Продолжения
async/awaitявляются микрозадачами. - Бесконечные цепочки микрозадач могут блокировать таймеры и отрисовку.
Часто задаваемые вопросы
Урок «Микрозадачи и промисы» бесплатный?
Да — полный текст урока «Микрозадачи и промисы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс JavaScript Academy, подпишись на CoddyKit PRO. Курс JavaScript Academy содержит 4 уроков всего.
Чему я научусь в уроке «Микрозадачи и промисы»?
Узнайте, почему обратные вызовы промисов выполняются первыми. Ты практикуешь JavaScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать JavaScript Academy?
Предыдущий опыт не требуется. JavaScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Микрозадачи и промисы»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке JavaScript Academy?
Да. Каждый урок JavaScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Стек вызовов
- Макрозадачи и очередь задач
- Микрозадачи и промисы
- queueMicrotask и порядок выполнения