Что выведет этот фрагмент на порядок событийного цикла и почему?
Что выведет следующий код и почему?
console.log('A');
setTimeout(() => console.log('B'), 0);
Promise.resolve().then(() => console.log('C'));
console.log('D');
Предскажите вывод и объясните.
Печатает A, D, C, B. Два синхронных console.log выполняются первыми, поэтому A, затем D. Колбэк Promise.then — микрозадача, а колбэк setTimeout — макрозадача; после завершения синхронного кода все микрозадачи опустошаются раньше любой макрозадачи, поэтому C печатается до B, хотя задержка таймера 0.
- ✗Думать, что колбэки срабатывают в порядке исходника, а не по типу очереди
- ✗Считать, что
setTimeout(…, 0)выполняется раньше ожидающих микрозадач - ✗Полагать, что движок блокируется на
setTimeoutили промисе на месте
- →Где в этом порядке находятся
queueMicrotaskи продолжения послеawait? - →Изменит ли добавление второго
.thenместо печатиB?
Решение
Синхронный код, затем микрозадачи (промисы), затем макрозадачи (setTimeout).
console.log('A'); // 1: синхронно
setTimeout(() => console.log('B'), 0); // макрозадача
Promise.resolve().then(() => console.log('C')); // микрозадача
console.log('D'); // 2: синхронно
// Вывод: A, D, C, B
Как это работает
Сначала движок выполняет весь синхронный код текущей задачи: печатаются A и D. Колбэки setTimeout и .then при этом лишь ставятся в очереди — таймер в очередь макрозадач, а .then в очередь микрозадач.
Когда синхронный код завершается, событийный цикл сначала полностью опустошает очередь микрозадач, поэтому печатается C. Только после этого берётся одна макрозадача, и печатается B. Нулевая задержка setTimeout не делает его микрозадачей — он всё равно ждёт опустошения микрозадач.