Как и когда Promise `.then`,` .catch` и `.finally` попадают в очередь микроблогов EventL oop? - PullRequest
0 голосов
/ 28 апреля 2020

.then, .catch и .finally приземляются в JS Событие L oop сразу после регистрации (когда соответствующий код интерпретируется в JS среде выполнения) или как-то иначе?

Менее теоретическое лицо этого вопроса следующее:

У меня есть следующий код (ссылка на JSBin (онлайн JS среда выполнения) )

l = console.log

const g = (title) => {
    return (a) => {
      l(title + a)
      return a+1;
    }
};

const gA = g("A ")
const gB = g("B ")

const throwError = (title) => {
    return (a) => {
      l(title + a)
      throw new Error("Error from promise " + title + a)
    }
}; 

promise = new Promise((resolve, reject) => {
  resolve(1)
})

l("Started application")

promise
  .then(gA)
  .then(gA)
  .then(throwError("A "))
  .catch(err => {
    l(err.message);
  })


promise
  .then(throwError("B "))
  .then(gB)
  .then(gB)
  .catch(err => {
    l(err.message);
  })

l("Finish main function")

который разрешает следующий вывод в консоли

"Started application"
"Finish main function"
"A 1"
"B 1"
"A 2"
"A 3"
"Error from promise A 3"
"Error from promise B 1"

Если бы обратные вызовы обещания выполнялись в порядке их регистрации, я ожидал бы, что "Error from promise B 1" будет выше в этом выводе. Но они появляются в конце. Почему это происходит?

Ответы [ 3 ]

1 голос
/ 28 апреля 2020

Do .then, .catch и .finally приземляются в JS Событие L oop сразу после регистрации или как-то иначе?

Эти методы обещания сами никогда земля в очереди. Очередь задач содержит реакций на обещание , которые в основном говорят: «Запустите обратные вызовы X / Y для результата обещания Z». (И они всегда являются парами then обратных вызовов, так как это то, что catch и finally используют для внутреннего использования.)

Эти реакции на обещание запланированы, как только обещание выполнено, или запланированы сразу во время then вызов, когда обещание уже было выполнено.

Если обратные вызовы обещания должны были быть выполнены в порядке их регистрации

Это так. Но это удерживает только за обещание . Единственное обещание в вашем коде, к которому вы присоединяете несколько обратных вызовов, это promise, а gA делает выполненным раньше, чем throwError("B "). Нет никаких гарантий для обратных вызовов, которые прикреплены к различным обещаниям, так как эти обещания все равно будут выполняться в разное время.

0 голосов
/ 28 апреля 2020

Из кода, которым вы делитесь, скажем, обещание A ниже:

promise
  .then(gA)
  .then(gA)
  .then(throwError("A "))
  .catch(err => {
    l(err.message);
  })

и обещание B ниже:

promise
  .then(throwError("B "))
  .then(gB)
  .then(gB)
  .catch(err => {
    l(err.message);
  })

Тогда, как мы знаем асинхронное поведение обещаний, консоль .log всегда завершает выполнение sh, прежде чем, следовательно, он печатает в самом начале, но в то же время обещание A & B уже запущено, но начнет печатать после console.logs.

В соответствии с порядком, т.е. обещание A сначала и обещание Во-вторых, оба падают на свои первые .then, то есть обещание A -> .then (1-е) выполняется, затем обещание b -> .then (1-го), следовательно, оно печатает

"A 1" //no exception called here hence will start execution of next .then
"B 1" //prints from throw called here and remains alive with 1 hence will never allow any of next .then() to execute.
"A 2" // 2nd .then executed
"A 3" // 3rd .then executed followed by throw and again remains alive with 3

Если возникает ошибка, то появляется поймать, а затем "throw" всегда будет в конечном итоге выполнять sh выполнение, так что согласно обещанию заказа A предшествует обещанию B, ниже показано

"Error from promise A 3" // 3 because of last successful increment
"Error from promise B 1" // 1 because of throw did not allow increment

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

0 голосов
/ 28 апреля 2020

Когда вы звоните resolve(), полное выполнение / отклонение обещания попадает в очередь в обещание микрозадачи. Затем, когда задача запускается, все соответствующие .then s / .catch s, прикрепленные к , которые обещают , запускаются в порядке прикрепления.

 promise.then(first);
 promise.then(second);

Теперь .then возвращает себя Обещание, чье решение вызывается при выполнении обратного вызова. Следовательно, .then, прикрепленный к Обещанию, возвращенному .then, выполняется по крайней мере на одну микротруду позже:

 const secondPromise = firstPromise.then(first);
 // one microtick after first run, secondPromise fullfills, and therefore attached .thens get run
 secondPromise.then(second);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...