Bagaimana menemukan janji mana yang tidak tertangani di Node.js UnhandledPromiseRejectionWarning?

177

Node.js dari versi 7 memiliki gula sintaksis async / menunggu untuk menangani janji dan sekarang dalam kode saya peringatan berikut muncul cukup sering:

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

Sayangnya tidak ada referensi ke garis di mana hasil tangkapan hilang. Apakah ada cara untuk menemukannya tanpa memeriksa setiap blok coba / tangkap?

pengguna1658162
sumber
Anda bisa menggunakan perpustakaan janji Bluebird dan kemungkinan akan memberi Anda jejak tumpukan.
jfriend00
3
Mungkin mendaftar ke unhandledRejectionacara Node akan membantu? Lihat dokumen . Callback Anda mendapatkan Errorobjek dan aktual Promise, dan saya percaya Errorobjek mungkin menyimpan jejak jejak.
YSK
Jika dua komentar sebelumnya tidak membantu, maka Can't set headers after they are sent.harus memberi Anda petunjuk di mana dalam kode Anda itu bisa terjadi (yaitu di suatu tempat Anda menetapkan header setelah header sudah dikirim - mungkin karena kegagalan dalam memahami kode asinkron , tapi itu dugaan)
Jaromanda X
hai pesan-pesan itu membantu memastikan dalam menemukan di mana dalam kode bug itu, tapi itu tidak semudah mengetahui barisnya.
user1658162
1
@ jfriend00 Ternyata itu adalah situasi di mana fungsi async melempar kesalahan - Node internal itu menjanjikan fungsi async, tidak pernah menggunakan Bluebird, jadi memiliki Bluebird tidak membantu dalam skenario itu.
Adam Reis

Jawaban:

297

dengarkan unhandledRejectionacara proses.

process.on('unhandledRejection', (reason, p) => {
  console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
  // application specific logging, throwing an error, or other logic here
});
cuixiping
sumber
35
Logging error.stack(atau dalam contoh di atas reason.stack) memberi Anda jejak stack penuh kesalahan.
Adam Reis
Terima kasih telah meletakkan process.ondaripada server.onsuka dalam banyak contoh lain yang saya temukan
PhillipHolmes
9
Saya berharap saya bisa mengatakan ini berhasil, tetapi tidak. Saya menggunakan Node 8.9.4.
ffxsam
2
Saya mencoba kode di atas dan tidak terdefinisi untuk kedua alasan, dan p? Ada saran? "Penolakan Tanpa Penanganan di: Janji {status: 'ditolak', alasan: tidak jelas} alasan: tidak ditentukan"
Jeremy
3
Saya menambahkan kode ini ke bagian atas app.jsfile simpul saya dan sayangnya tidak ada yang dicatat. Node v10.13.0.
user1063287
71

Cara yang benar untuk menunjukkan stacktrace penuh untuk penolakan ES6 Promise yang tidak tertangani, adalah menjalankan Node.js dengan --trace-warningsbendera. Ini akan menampilkan stacktrace penuh untuk setiap peringatan, tanpa harus mencegat penolakan dari dalam kode Anda sendiri. Sebagai contoh:

node --trace-warnings app.js

Pastikan trace-warningsbendera datang sebelum nama .jsfile Anda ! Jika tidak, bendera akan ditafsirkan sebagai argumen untuk skrip Anda, dan itu akan diabaikan oleh Node.js sendiri.

Jika Anda ingin benar-benar menangani penolakan yang tidak ditangani (mis. Dengan mencatatnya), maka Anda mungkin ingin menggunakan unhandled-rejectionmodul saya sebagai gantinya, yang menangkap semua penolakan yang tidak ditangani untuk setiap implementasi Janji utama yang mendukungnya, dengan pengatur kejadian tunggal.

Modul yang mendukung Bluebird, ES6 Promises, Q, WhenJS, es6-promise, then/promise, dan apa yang paling sesuai dengan salah satu spesifikasi penolakan tertangani (rincian lengkap dalam dokumentasi).

Sven Slootweg
sumber
20
Menggunakan node 7.8.0 dan semua ini memberi saya jejak stack untuk sekelompok modul simpul internal. (simpul: 10372) UnhandledPromiseRejectionWarning: Penolakan janji yang tidak tertangani (id penolakan: 2): tidak ditentukan pada emitWarning (internal / proses / janji.js: 59: 21) di emitPendingUnhandledRejections (internal / proses / janji.js: 86: 11) pada saat proses ._tickDomainCallback (internal / proses / next_tick.js: 136: 7)
Will Lovett
3
Saya tidak melihat output apa pun yang menunjukkan di mana masalah janji tidak tertangani.
Jason Leach
Saya menambahkan ini untuk package.jsonmemulai skrip dan sayangnya tidak ada yang dicatat. Node v10.13.0.
user1063287
1
@ user1063287 Pastikan bendera berada di tempat yang benar dalam perintah Anda. Saya baru saja menambahkan pembaruan pada jawabannya, untuk menekankan bahwa itu harus dilakukan sebelum nama skrip.
Sven Slootweg
2
Anda kemungkinan melihat jejak tumpukan peringatan penghentian, bukan kesalahan asli yang tidak ditangani (yang seharusnya berada di atas peringatan penghentian).
Sven Slootweg
7

Logging dengan stack stack

Jika Anda mencari lebih banyak pesan kesalahan bermanfaat. Coba tambahkan ini ke file simpul Anda. Seharusnya menampilkan jejak tumpukan penuh di mana kecelakaan Anda terjadi.

process.on('unhandledRejection', (error, p) => {
  console.log('=== UNHANDLED REJECTION ===');
  console.dir(error.stack);
});
joshuakcockrell
sumber
Satu-satunya perbedaan fungsional adalah melakukan console.dir pada properti stack kesalahan itu. Perbedaan yang cukup besar dalam output dibandingkan dengan jawaban yang diterima.
joshuakcockrell