Node.js UnhandledPromiseRejectionWarningで処理されていないプロミスを見つける方法は?


177

バージョン7のNode.jsには、promiseを処理するための非同期/待機シンタックスシュガーがあり、私のコードでは次の警告が頻繁に表示されます。

(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.

残念ながら、キャッチが欠落している行への参照はありません。すべてのtry / catchブロックをチェックせずにそれを見つける方法はありますか?


Bluebird promiseライブラリを使用すると、スタックトレースが得られる可能性があります。
jfriend00

3
おそらく、NodeのunhandledRejectionイベントに登録すると役立ちますか?docsを参照してください。あなたのコールバックは、取得Error対象と実際をPromise、と私は信じているErrorオブジェクトがスタックトレースを保持しているかもしれません。
YSK 2017年

前の2つのコメントが役に立たないCan't set headers after they are sent.場合は、コード内でそれが発生している可能性がある場所(つまり、ヘッダーがすでに送信された後にヘッダーを設定している場所-おそらく非同期コードの理解に失敗したため) 、しかしそれは推測です)
Jaromanda X

こんにちはそのメッセージは、コードのどこにバグがあるかを確実に見つけるのに役立ちますが、行を知るほど簡単ではありません。
user1658162 2017年

1
@ jfriend00非同期関数がエラーをスローしている状況であることが判明しました-非同期関数に対するこれらの内部ノードプロミスは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
これがうまくいったとは言えませんが、うまくいきませんでした。私はノード8.9.4にいます。
ffxsam 2018

2
私は上記のコードを試してみましたが、両方の理由で未定義になりました、そしてp?助言がありますか?"未処理の拒否:約束{状態: '拒否'、理由:未定義}理由:未定義"
Jeremy

3
このコードをノードapp.jsファイルの先頭に追加しましたが、残念ながら何も記録されません。ノードv10.13.0
user1063287 2018年

71

正しい未処理ES6約束拒否のための完全なスタックトレースを表示する方法は、とのNode.jsを実行することです--trace-warningsフラグ。これにより、独自のコード内から拒否をインターセプトする必要なく、すべての警告の完全なスタックトレースが表示されます。例えば:

node --trace-warnings app.js

trace-warningsフラグがファイル名のに来ることを確認してください.js!それ以外の場合、フラグはスクリプトの引数として解釈され、Node.js自体によって無視されます。

未処理の拒否を実際に処理したい場合(ログに記録するなど)、unhandled-rejection代わりにmy module を使用すると、単一のイベントハンドラーで、それをサポートするすべての主要なPromises実装の未処理の拒否をすべてキャッチできます。

そのモジュールは、ブルーバード、ES6の約束、Q、WhenJS、サポートしes6-promisethen/promise未処理の拒絶仕様(ドキュメントの完全な詳細)のいずれかに適合していること、そして何かを。


20
ノード7.8.0を使用すると、内部ノードモジュールの束のスタックトレースが得られます。(node:10372)UnhandledPromiseRejectionWarning:Unhandled Promise Rejection(rejection id:2):undefined at emitWarning(internal / process / promises.js:59:21)at emitPendingUnhandledRejections(internal / process / promises.js:86:11)at process ._tickDomainCallback(内部/プロセス/ next_tick.js:136:7)
ウィルラベット

3
未処理のpromiseの問題がどこにあるかを示す出力が表示されません。
Jason Leach、2018

package.jsonスクリプトを開始するためにこれを追加しましたが、残念ながら何も記録されませんでした。ノードv10.13.0
user1063287 2018年

1
@ user1063287フラグがコマンドの正しい場所にあることを確認してください。スクリプト名のに置く必要があることを強調するために、回答に更新を追加しました。
Sven Slootweg

2
おそらく、元の未処理のエラーではなく、非推奨警告のスタックトレースを見ているは​​ずです(非推奨警告の上にあるはずです)。
Sven Slootweg、

7

スタックトレースを使用したロギング

役立つエラーメッセージの詳細を探している場合。これをノードファイルに追加してみてください。クラッシュが発生している完全なスタックトレースが表示されます。

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

機能的な違いは、エラーのスタックプロパティでconsole.dirを実行することだけです。受け入れられた回答と比較した出力のかなりの違い。
joshuakcockrell
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.