Як знайти, які обіцянки виконуються в Node.js UnhandledPromiseRejectionWarning?


177

Node.js з версії 7 має синтаксичний цукор async / очікує на обробку обіцянок, і тепер у моєму коді часто виникає таке попередження:

(node:11057) UnhandledPromiseRejectionWarning: Unhandled promise 
rejection (rejection id: 1): ReferenceError: Error: Can't set headers 
after they are sent.
(node:11057) 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.

На жаль, немає посилання на рядок, де улов відсутній. Чи є спосіб знайти його, не перевіряючи кожен блок спробу / лову?


Ви можете скористатися бібліотекою обіцянок Bluebird, і це, ймовірно, дасть вам стежити за стеком.
jfriend00

3
Можливо, реєстрація до unhandledRejectionподії Node допоможе? Дивіться документи . Ваш зворотний дзвінок отримує Errorоб'єкт і фактичний Promise, і я вважаю, що Errorоб'єкт може містити стек стека.
YSK

Якщо два попередні коментарі не допомагають, то вам Can't set headers after they are sent.слід дати зрозуміти, де у вашому коді це може відбуватися (тобто десь ви встановлюєте заголовки після того, як заголовки вже були б надіслані - мабуть, через нерозуміння асинхронного коду , але це здогад)
Jaromanda X

привіт, що повідомлення допомагають точно знайти місце в коді помилки, але це не так просто, як знати рядок.
користувач1658162

1
@ jfriend00 Виявляється, це була ситуація, коли функція асинхронізації кидала помилку - ці внутрішні обіцянки Node для функцій async не використовують Bluebird ніколи, тому наявність Bluebird не допомагає в цьому сценарії.
Адам Рейс

Відповіді:


297

прослухати unhandledRejectionподію процесу.

process.on('unhandledRejection', (reason, p) => {
  console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
  // application specific logging, throwing an error, or other logic here
});

35
Ведення журналу error.stack(або у наведеному вище прикладі reason.stack) дає вам повний слід стеку помилки.
Адам Рейс

Дякую за введення , process.onа не server.onяк і в багатьох інших прикладах , які я знайшов
PhillipHolmes

9
Я б хотів сказати, що це спрацювало, але це не так. Я на Node 8.9.4.
ffxsam

2
Я спробував вищевказаний код і не визначився з обох причин, і p? Будь-які пропозиції? "Неопрацьоване відхилення за адресою: Обіцяємо {стан:" відхилено ", причина: невизначено} причина: невизначено"
Джеремі

3
Я додав цей код у верхню частину мого app.jsфайлу вузла, і на жаль нічого не реєструється. Вузол v10.13.0.
користувач1063287

71

Правильний шлях , щоб показати повну трасування стеки для необроблених отбраковок ES6 Promise, є запуск Node.js з --trace-warningsпрапором. Це покаже повний стек-трек для кожного попередження, не перехоплюючи відхилення з вашого власного коду. Наприклад:

вузол - сліди-попередження app.js

Переконайтесь, що trace-warningsпрапор надходить до назви вашого .jsфайлу! В іншому випадку прапор буде інтерпретований як аргумент вашого сценарію, і він буде ігноруватися самим Node.js.

Якщо ви хочете насправді обробити необроблені відхилення (наприклад, за допомогою реєстрації їх), ви можете unhandled-rejectionзамість цього використати мій модуль, який фіксує всі необроблені відхилення для кожної основної реалізації Обіцянь, яка його підтримує, з одним обробником подій.

Цей модуль підтримує Bluebird, ES6 Promises, Q, WhenJS, es6-promise, then/promiseі що - небудь , який відповідає будь-якому з необробленої специфікації відбраковування (повні деталі в документації).


20
Використання вузла 7.8.0 і все це дає мені - стек стека для купки внутрішніх модулів вузлів. (вузол: 10372) UnhandledPromiseRejectionWarning: Нерозподілене відхилення обіцянки (ідентифікатор відхилення: 2): невизначений при emitWarning (внутрішній / процес / promises.js: 59: 21) при emitPendingUnhandledRejections (внутрішній / процес / promises.js: 86: 11) під час обробки ._tickDomainCallback (внутрішній / процес / next_tick.js: 136: 7)
Will Lovett

3
Я не бачу жодного результату, який би показував, де стоїть проблема без обігу.
Джейсон Ліч

Я додав це до package.jsonсценарію запуску, і, на жаль, нічого не реєстрували. Вузол v10.13.0.
користувач1063287

1
@ user1063287 Переконайтесь, що прапор знаходиться у правильному місці у вашій команді. Щойно я додав оновлення до відповіді, щоб підкреслити, що воно повинно пройти перед назвою сценарію.
Свен Слоотвег

2
Ви, ймовірно, дивитеся на стек стеження попередження про депресацію, а не на оригінальну необроблену помилку (яка повинна бути десь над попередженням про депресію).
Свен Слоотвег

7

Ведення журналу за допомогою сліду стека

Якщо ви шукаєте більше корисного повідомлення про помилку. Спробуйте додати це до файлу вузла. Він повинен відображати повний слід стека, де відбувається збій.

process.on('unhandledRejection', (error, p) => {
  console.log('=== UNHANDLED REJECTION ===');
  console.dir(error.stack);
});

Єдина функціональна відмінність - це консоль.dir щодо властивості стека помилки. Досить різниця у виході порівняно з прийнятою відповіддю.
Джошуккокрелл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.