Браузеры все еще молча проглатывают необработанные отклоненные обещания? А как насчет узла? - PullRequest
0 голосов
/ 28 августа 2018

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

Этот совет, похоже, устарел. Современные браузеры и современные версии Node, похоже, выводят предупреждения, когда отклоненные обещания не обрабатываются. Возьми этот код:

async function thisIsGoingToFail() {
  await Promise.reject();
  console.log('this should not print, as the line above should error');
}

async function main() {
  await thisIsGoingToFail();
}

main();

Если вы запустите это в Node, вы получите:

(node:20760) UnhandledPromiseRejectionWarning: undefined
(node:20760) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:20760) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

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

main().catch(err => { console.err(err) });

Но не похоже, что это было необходимо. Итак, вот мои вопросы:

  • Правда ли, что современные браузеры и современный Node всегда будут показывать предупреждение для необработанных отклоненных обещаний? Какие номера версий реализации поддерживают это?
    • (Обратите внимание, что браузер не должен поддерживать событие unhandledrejection, чтобы вывести предупреждение, когда обещание не обработано.)
  • Нужно ли нам иметь функции верхнего уровня catch, как вам часто советуют, или же столь же полезно позволить реализации показывать предупреждение?

1 Ответ

0 голосов
/ 28 августа 2018

Большинство современных реализаций выводят на консоль предупреждения, когда отклоненные обещания не обрабатываются, но не все:

  • Node.js Начиная с версии 6.6.0 (см. changelog ):

    обещания: необработанные отклонения теперь выдают предупреждение процесса после первого тика. (Бенджамин Грюнбаум) # 8223

    В будущих версиях отклонения обещаний, которые не обрабатываются, завершат процесс Node.js с ненулевым кодом выхода.

  • Firefox действительно показывает предупреждение, но я не могу найти, какая была первая версия, которая делает это. MDN документы сказать это:

    Мы принимаем следующую стратегию: если обещание отклонено во время его сборки мусора и , если обещание находится в конце цепочки обещаний (то есть, что Promise.then никогда не вызывался) , затем мы печатаем предупреждение.

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

  • Chrome действительно показывает предупреждение, но снова я не могу найти документацию, указывающую, какая версия является первой, чтобы сделать это. Chrome> = 49 идет еще дальше и поддерживает unhandledrejection событие , которое позволяет добавить пользовательский обработчик событий для обработки всех необработанных отклоненных обещаний.

  • Safari также показывает предупреждение, и, поскольку версия> = 11, также поддерживает событие unhandledrejection.

  • Edge , похоже, пока не поддерживает его, основываясь на этой открытой проблеме GitHub в Microsoft / ChakraCore .

Похоже, что большинство современных браузеров (кроме Edge) действительно отображают предупреждения для необработанного отклонения, но нет четкой документации, гарантирующей, что предупреждение будет отображаться или показываться быстро. Обработка события unhandledrejection кажется хорошей идеей для браузеров, которые его поддерживают.


tldr; На момент написания, похоже, что лучше всего по-прежнему иметь обработчики отклоненных обещаний верхнего уровня с catch (чтобы избежать проглатывания ошибок в Edge и завершения процессов в Node). Для Chrome и Safari может быть полезно использовать событие unhandledrejected.

...