// Каков будет порядок логов и почему? setTimeout(() => console.log(2), 0); console.log(1); new Promise((res) => { console.log(6); res(); console.log(3); }) .then(() => { console.log(4); setTimeout(() => console.log(7), 0); }); console.log(5);
🎯 Зачем спрашивают
Проверка базового понимания работы event loop, микротасок и макротасок.
📝 Ответ
Прежде чем приступать к задаче, давайте вспомним порядок выполнения кода:
- синхронный код
- микротаски —
Promise,Mutation Observer
- макротаски — API окружения браузер/Node.js (
setTimeout,setInterval,setImmediate)
Точнее о порядке выполнения
После завершения текущего стека синхронного кода движок полностью вычищает очередь микротасок, затем (в браузере) может произойти шаг рендеринга, и только после этого выполняется следующая макротаска
Пройдемся по коду и расставим порядок выполнения. Сперва найдем весь синхронный код:
setTimeout(() => console.log(2), 0); // <-- Ставим макротаску #1 console.log(1); // 1 new Promise((res) => { console.log(6); // 2 res(); // <-- Ставим микротаску #1 console.log(3); // 3 }) .then(() => { console.log(4); setTimeout(() => console.log(7), 0); }); console.log(5); // 4
Не забудьте, что конструктор
Promise выполняется синхронно!
Мы разметили синхронный код. После синхронного кода у нас уже запланировано:
- 1 микротаска →
.then
- 1 макротаска →
setTimeout(() => console.log(2)))
Далее идет выполнение микротасок:
setTimeout(() => console.log(2), 0); console.log(1); // 1 new Promise((res) => { console.log(6); // 2 res(); console.log(3); // 3 }) .then(() => { console.log(4); // 5 <--! setTimeout(() => console.log(7), 0); // <-- Ставим макротаску #2 }); console.log(5); // 4
Далее выполняются макротаски в порядке постановки:
setTimeout(() => console.log(2), 0); // 6 <--! console.log(1); // 1 new Promise((res) => { console.log(6); // 2 res(); console.log(3); // 3 }) .then(() => { console.log(4); // 5 setTimeout(() => console.log(7), 0); // 7 <--! }); console.log(5); // 4
Итоговый лог будет (что будет в консоли):
// 1 6 3 5 4 2 7
⚖️ Компромиссы
✅ Плюсы | ❌ Минусы |
Понимание event loop помогает писать предсказуемый код и избегать багов в async логике. | Такие вопросы часто тестируют память, а не реальный навык. Лучше уметь объяснить принцип, а не просто порядок. |
🔎 Встречные вопросы
- Что такое starvation микротасок и как её не допустить?
- Для чего нужен
queueMicrotask()? Какие способы использования?
🚩 Красные флаги
- Кандидат говорит, что
Promiseвыполняется асинхронно «всегда» (не понимает, что конструктор — синхронный).
- Путает микротаски и макротаски.
- Называет
setTimeout(..., 0)«выполнением сразу после кода».
🛠 Практика
Задача 1
// Каков порядок логов? Почему? console.log(1); setTimeout(() => console.log(2), 0); Promise.resolve().then(() => console.log(3)); console.log(4);
Задача 2
// Каков порядок логов? Почему? console.log('A'); setTimeout(() => console.log('B'), 0); queueMicrotask(() => console.log('C')); console.log('D');
Задача 3
// Каков порядок логов? Почему? Promise.resolve() .then(() => { console.log('A'); Promise.resolve().then(() => console.log('B')); }) .then(() => console.log('C'));
Задача 4
// Каков порядок логов? Почему? setTimeout(() => console.log('1'), 0); Promise.resolve() .then(() => console.log('2')) .then(() => console.log('3')); queueMicrotask(() => console.log('4')); console.log('5');
📚 Источники / ссылки
MDN Web DocsJavaScript execution model - JavaScript | MDN

JavaScript execution model - JavaScript | MDN
This page introduces the basic infrastructure of the JavaScript runtime environment. The model is largely theoretical and abstract, without any platform-specific or implementation-specific details. Modern JavaScript engines heavily optimize the described semantics.