Порядок исполнения Javascript обещаний, когда присоединены разные цепочки обещаний - PullRequest
2 голосов
/ 20 марта 2020

Я хотел проверить переносимость объекта promise, создав promise и передав его вокруг, а другие прикрепили к нему then. Вывод далек от того, что я ожидал, и я не понимаю, как он выполняется.

const wait = time => {
  return new Promise((res, rej) => {
    setTimeout(res, time);
  });
};

const promise = wait(5000)
  .then(() => console.log('1'));

promise
  .then(() => console.log('2'))
  .then(() => console.log('3'));

promise
  .then(() => console.log('4'))
  .then(() => console.log('5'));

вывод:

1
2
4
3
5

Я отлаживаю код, и вот что я наблюдал. вызов wait(5000) вызывает конструктор Promise, который вызывает API setTimeout, передавая res callback и Promise объект возвращается обратно. затем он начинает регистрировать все then с 1 по 5 в том же порядке. Через 5 секунд он вызывает res из Promise объекта, который вызывает цепочки обещаний.

На мой взгляд, then API добавляет все callbacks в массив или что-то в этом роде, от 1 до 5, и когда вызывается res, он начинает вызывать callbacks из массива один за другим. один (FIFO), который должен создавать журналы 1 2 3 4 5, а не 1 2 4 3 5.

Как это не выполняется, если они регистрируются на основной promise?

1 Ответ

4 голосов
/ 21 марта 2020

Во-первых, когда вы делаете это:

promise.then(...).then(...)

, который присоединяет один обработчик .then() к promise, а второй .then() присоединяется к новому обещанию, которое возвращает первое .then() .

Итак, когда promise разрешается, первый .then() запланирован на следующий тик события l oop. Тогда, только когда первый .then() завершится, он запланирует запуск второго .then() на следующем тике события l oop (он не запускается на этом тике события l oop).

Когда вы делаете это:

promise
  .then(() => console.log('2'))
  .then(() => console.log('3'));

promise
  .then(() => console.log('4'))
  .then(() => console.log('5'));

И затем, когда promise разрешается, then(2) и then(4), которые являются единственными двумя обработчиками .then() в этом фрагменте кода, непосредственно подключенном на promise запланировано выполнение на следующем тике события l oop. После этого следующего шага сначала запускается then(2), а затем then(4). Так как они оба были привязаны к одному и тому же обещанию, они выполняются в режиме FIFO, первый из них запускается первым. Когда then(2) выполняется, он планирует then(3) для запуска на следующем тике события l oop, а когда then(4) запускается, он планирует then(5) для запуска на следующем тике события l oop.

Итак, после выполнения then(2) и then(4) при следующем тике события l oop вы увидите then(3) и then(5) run, и это объясняет последовательность, которую вы видите в консоли:

1
2
4
3
5

Полагаю, вы не удивлены, что сначала запускается then(1), поэтому я не добавил это к объяснению.

Как это не выполняется, если они регистрируются в главном обещании?

Три обработчика .then(), подключенные непосредственно к promise, работают в том порядке, в котором они были присоединены. Что, по-видимому, смущает вас, так это то, что обработчики .then() не привязаны напрямую к promise, а к новым обещаниям, которые возвращает promise.then().

.then() возвращает новое обещание, потому что оно может не разрешиться немедленно. Если обратный вызов внутри .then() сам возвращает обещание, то обещание, которое возвращает .then(), не разрешается немедленно. Он должен ждать, пока обещание о том, что возвращенный обратный вызов .then() также не разрешится.

По-моему, API добавляет все обратные вызовы в массив или что-то в этом роде, от 1 до 5 и один раз. вызывается res, он начинает вызывать обратные вызовы из массива один за другим (FIFO), который должен создавать журналы 1 2 3 4 5, а не 1 2 4 3 5.

Ну, 1, 2 и 4 действительно добавлен к тому же массиву .then() обратных вызовов обработчика для объекта promise. Но, как объяснено выше, 3 и 5 находятся на отдельных обещаниях, которые были созданы .then(), к которым они прикованы. Итак, 1, 2 и 4 выполнены FIFO. Но 3 и 5 откладываются до следующего тика события l oop.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...