Как найти необработанный отказ, который отклонен без ошибки - PullRequest
0 голосов
/ 15 апреля 2020

Скажем, у меня есть несколько кодов, как показано ниже:

process.on('unhandledRejection', (reason, promise) => {
  console.log(reason, promise)
})

Promise.reject()

Promise.reject, вызываемый без каких-либо параметров, и обработчик unhandledRejection выводит что-то вроде undefined Promise { <rejected> undefined }. Не было никакой информации, чтобы найти настоящее обещание. Так, как я могу получить контекст об отклоненном обещании в этом случае?

Заранее спасибо.

1 Ответ

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

Не имеет значения, есть ли в обещании ошибка или нет.

Отклоненные обещания обычно отличаются от исключений . Они асинхронные. И это всего лишь объекты.

Синхронная обработка ошибок

Вы можете определить, где было сгенерировано исключение:

if(true){
  throw undefined //Definitely here
}

Однако оно становится более Сложно, если у вас есть функции:

function throwUndefined(){
  throw undefined //Here?
}

function maybeThrow(throwException){
  if(throwException){
    throwUndefined() //Or here?
  }
}

maybeThrow(true) //Or here?

На самом деле, оба три места. Вот где приходит стек ошибки.

Он представляет стек вызовов в момент возникновения исключения. В приведенном выше примере это будет что-то вроде:

throwUndefined (line 2) 
maybeThrow (line 7)
main (line 11)

Но обещания разные

Этот материал в стеке может быть очень полезен для синхронного кода, но ... асинхронность выходит за рамки stack!

Когда основной скрипт завершает работу и вырывается из стека, код не останавливается: асинхронность начинается именно там.

На шаг выше стека

Событие l oop включается и начинает обрабатывать «волшебные» вещи, такие как обещания и тайм-ауты.

А теперь, где находится обещать в конце кода?

const a = new Promise((resolve) => { //Here?
  setTimeout(() => {
    resolve()
    b = a //Or here?
  }, 100)
})
a.then(() => { //Here?
  console.log(b) //Here?
})
let b //Or maybe here?

Оба этих места!

Однако это не может быть представлено линейной структурой (например, стеком), поскольку некоторые части меняются со временем.

Если обещание отклоняется асинхронно, оно не останавливает выполнение кода. Обработчики могут быть присоединены позже:

const a = Promise.reject() //If the code would terminate here, you couldn't add the catch listener
a.catch(console.error)

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

Рассмотрим следующее:

let a = Promise.reject()
a = undefined

//Warning: `a` was rejected! But was it? Well, no... `a` is just `undefined`

Или более реалистичный c пример:

const array = [Promise.resolve(), Promise.resolve(), Promise.reject(), Promise.resolve(), Promise.resolve(), Promise.resolve(), Promise.resolve(), Promise.resolve()]
for(const promise of array){
  const x = promise.then() //Forward data to `x`
}

//Warning: `x` was rejected! Exactly which  `x` of the 8? 

Это нормально, но, пожалуйста, ответьте на мой вопрос!

Как найти обещание?

Все просто: у вас есть ссылка на него! Что еще вам нужно?

Если вы сравните ссылку в аргументе promise используемых вами обещаний, вы сможете найти, какое из них было отклонено, и оттуда нетрудно выяснить где это произошло.

И напоследок совет: обработайте все обещания (или цепочки обещаний), даже те, которые вы не ожидаете отклонить.

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