Сначала завершается синхронный код, затем опустошается очередь микрозадач, включая добавленные во время её обработки. Таймер не прерывает эту работу. Отслеживайте момент постановки в очередь, а не запоминайте рейтинг приоритетов API.
Задача 1: Promise, вложенная микрозадача и таймер
Запустите код одним скриптом на новой странице браузера или вставьте весь блок в консоль. До запуска выпишите шесть строк вывода и отдельно — ожидающие микрозадачи. setTimeout планирует будущую задачу: нулевая задержка не означает немедленный вызов обработчика.
Порядок вывода: start → end → promise → microtask → nested → timer. К завершению синхронной части уже запланированы обработчик Promise и явная микрозадача. Вложенная nested добавится в конец очереди только при выполнении обработчика Promise.
console.log('start');
setTimeout(() => console.log('timer'), 0);
Promise.resolve().then(() => {
console.log('promise');
queueMicrotask(() => console.log('nested'));
});
queueMicrotask(() => console.log('microtask'));
console.log('end');Выпишите очередь после каждого шага
В таблице указаны только ожидающие обработчики: выполняющийся уже извлечён из очереди. Когда выполняется promise, microtask уже ждёт, поэтому nested оказывается после него. Правила «любой Promise важнее любого queueMicrotask» здесь нет.
Модель HTML предусматривает очереди задач и возможности обновления отрисовки. В этом маленьком примере один таймер и нет конкурирующих источников событий, поэтому вывод определён. Из него нельзя вывести общий порядок сетевых событий, пользовательского ввода и таймеров или обещать перерисовку после каждого обработчика.
| После шага | Ожидающие микрозадачи | Накопленный вывод |
|---|---|---|
| Синхронный скрипт | promise, microtask | start, end |
| Обработчик promise | microtask, nested | start, end, promise |
| Обработчик microtask | nested | start, end, promise, microtask |
| Обработчик nested | пусто | start, end, promise, microtask, nested |
| Обработчик timer | пусто | start, end, promise, microtask, nested, timer |
Задача 2: приостанавливает ли функцию await 0?
Да. Вызов async-функции начинает выполнять её тело синхронно. Но await приостанавливает продолжение этой функции даже для значения, которое не является ожидающим Promise. Вызывающий код продолжает работу. В примере продолжение review попадает в очередь раньше следующего вызова queueMicrotask.
Вывод: script:start → review:start → script:end → review:resume → queued. Перенесите queueMicrotask выше review() и снова предскажите последние две строки: теперь queued окажется перед review:resume. Такая правка проверяет понимание постановки в очередь, а не память об исходном ответе.
async function review() {
console.log('review:start');
await 0;
console.log('review:resume');
}
console.log('script:start');
review();
queueMicrotask(() => console.log('queued'));
console.log('script:end');Как объяснить решение на собеседовании
Сначала уточните среду выполнения, затем пройдите синхронные вызовы. Отмечайте место постановки каждого обработчика в очередь и различайте вызов функции и планирование её продолжения. После обработчика, который добавляет новую работу, заново выписывайте очередь. Так объяснение можно проверить, даже если вы случайно перепутали одну подпись.
Для дополнительного вопроса замените вложенную микрозадачу ещё одним таймером: nested больше не будет частью той же проверки очереди микрозадач. Другой вопрос — что произойдёт, если микрозадача постоянно добавляет саму себя. Она может бесконечно задерживать следующие задачи и отрисовку. Не запускайте неограниченный вариант в рабочей вкладке.
- Код async-функции до первого await выполняется синхронно.
- Нулевой таймер означает возможность выполнения позже, а не ровно через ноль миллисекунд.
- В этих задачах обработчики Promise и queueMicrotask следуют порядку постановки в очередь.
- Порядок вывода в консоль не является моделью частоты кадров браузера.
Как повторять тему, не заучивая ответ
Сохраните код без ответа. При следующем повторении восстановите вывод и объясните два изменения очереди: выполнение обработчика Promise и достижение await. Затем измените одну строку и предскажите результат до запуска. Карточка с шестью заученными подписями сама по себе не проверяет понимание.
Для дополнительных вопросов используйте сборник по JavaScript. RecallDeck помогает возвращаться к понятиям по расписанию; выполнение и изменение кода оставьте отдельной частью подготовки в редакторе или браузере.
Коротко
Частые вопросы
Promise всегда выполняется раньше setTimeout?
В первой задаче уже запланированный обработчик Promise выполняется раньше таймера. Если Promise завершится позже, таймер может успеть выполниться до появления готового обработчика этого Promise.
queueMicrotask быстрее Promise.then?
Здесь разбирается порядок выполнения, а не производительность. Оба механизма планируют микрозадачи; при выборе API учитывайте его семантику, в том числе обработку ошибок.
Можно ли перенести ответ на Node.js?
Использованные API доступны и в Node.js, но вывод нельзя автоматически обобщать на process.nextTick, setImmediate, фазы ввода-вывода и различия модульного контекста.
Источники
Источники и редакционная политика
Сведения проверены 21 октября 2026 г. Ссылки рядом с разделами указывают источники фактов и технических объяснений. Выводы, учебные сценарии и рекомендации по подготовке — редакционная работа RecallDeck.
От чтения к воспроизведению
Отрепетируйте полный цикл интервью.
RecallDeck возвращает сложные темы по расписанию и помогает удерживать в памяти язык, SQL, архитектуру и поведенческие истории.