Задать вопрос

Почему именно такой порядок вывода в консоль?

new Promise((resolve) => resolve()) // P1
  .then(() => { // C1
    console.log(1);
    return new Promise((resolve) => resolve());
  })
  .then(() => console.log(2)); // C2

new Promise((resolve) => resolve()) // P2
  .then(() => console.log(3)) // C3
  .then(() => console.log(4)) // C4
  .then(() => console.log(5)) // C5
  .then(() => console.log(6)); // C6


Ответ: 1, 3, 4, 5, 2, 6.

Почему 4, 5 успевают проскочить, а 6 нет?
Я понимаю, что когда из then возвращается промис, создаётся микрозадача чтоб его обработать, но не понимаю, почему вообще успевают проскочить в консоль 4, 5 перед 2.
Для удобства обсуждения, в комментариях к коду написал краткие аббревиатуры.
  • Вопрос задан
  • 209 просмотров
Подписаться 4 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 2
@NikitaLikosov
Представим eventloop step by step
1. Мы синхронно выполнили код и получили 2 микротаска с вызовом 1 и вызовом 3
2. Микротаски вызвались и создали еще 2 микротаска с вызовом 4 и вот этим вот промисом return new Promise((resolve) => resolve());(функция в then его просто вернула, а в следующий then он должен попасть выполненным, так что, js его отдельно сначала должен выполнять )
3. После вызова прошлых микротасок мы получили микротаск с вызовом 5 и 2
4. Осталось вызвать микротаск с 6 и все
Ответ написан
sergiks
@sergiks Куратор тега JavaScript
♬♬
Интересный вопрос! Больше экспериментов.
Вспомогательная функция для читаемости:
const log = (value, returnPromise) => () => {
  console.log(value);
  if (returnPromise) return Promise.resolve();
};
Возвращает функцию, которая обычный console.log() с переданным значением. И если второй аргумент трушный, то вернёт отрезолвленный промис.

Эксперимент 1. «Застёжка-молния»
Promise.resolve()
  .then(log('a1'))
  .then(log('a2'))
  .then(log('a3'))
  .then(log('a4'))
  .then(log('a5'))
  .then(log('a6'))
;

Promise.resolve()
  .then(log('b1'))
  .then(log('b2'))
  .then(log('b3'))
  .then(log('b4'))
  .then(log('b5'))
  .then(log('b6'))
;
Выводит поочередные a1 b1 a2 b2 a3 b3 ...
Эксперимент 2. «Отстаём на 2»

Единственное отличие: в первом А возвращаем отресолвленный промис.
Promise.resolve()
  .then(log('a1', true))
  .then(log('a2'))
  .then(log('a3'))
  .then(log('a4'))
  .then(log('a5'))
  .then(log('a6'))
;

Promise.resolve()
  .then(log('b1'))
  .then(log('b2'))
  .then(log('b3'))
  .then(log('b4'))
  .then(log('b5'))
  .then(log('b6'))
;

Выводит
a1 b1 b2 b3 a2 b4 a3 b5 a4 b6 a5 a6
А-шки после 1-й отстают на 2, пропустив вперёд b2 и b3.

Очередь микрозадач работает как FIFO буфер: первый пришёл, первый ушёл.

Цепочка из then() выполняется асинхронно. После выполнения очередного, создаётся следующий microtask. Несколько цепочек, как видно из 1-го эксперимента, выполняются параллельно-пошагово, «молнией».

Возврат созданного выполненного промиса, и ожидание его разрешения вызывает задержку в очереди микрозадач на 2 шага. Пока не совсем понимаю, почему именно на 2. Один – это ожидание ресолва промиса, который вернул then(). Второй – ?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы