วิธีค้นหาสัญญาที่ไม่ได้จัดการใน Node.js UnhandledPromiseRejectionWarning?


177

Node.js จากเวอร์ชัน 7 มี async / คอยน้ำตาล syntactic สำหรับจัดการสัญญาและตอนนี้ในรหัสของฉันคำเตือนต่อไปนี้เกิดขึ้นค่อนข้างบ่อย:

(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เหตุการณ์ของโหนดจะช่วยได้ไหม ดูเอกสาร โทรกลับของคุณได้รับErrorวัตถุและของจริงPromiseและฉันเชื่อว่าErrorวัตถุนั้นอาจมีร่องรอยการติดตามสแต็ก
YSK

หากความคิดเห็นก่อนหน้าทั้งสองไม่ช่วยคุณCan't set headers after they are sent.ควรให้เบาะแสว่ารหัสของคุณอาจเกิดขึ้นได้ที่ไหน (เช่นบางที่คุณตั้งค่าส่วนหัวหลังจากส่วนหัวจะถูกส่งไปแล้ว - น่าจะเป็นเพราะความล้มเหลวในการทำความเข้าใจโค้ดอะซิงโครนัส แต่นั่นเป็นการคาดเดา)
Jaromanda X

สวัสดีว่าข้อความช่วยในการค้นหาข้อผิดพลาดในโค้ดได้อย่างไร btw มันไม่ง่ายเหมือนการรู้บรรทัด
user1658162

1
@ jfriend00 ปรากฎว่ามันเป็นสถานการณ์ที่ฟังก์ชั่น async กำลังขว้างข้อผิดพลาด - โหนดภายในเหล่านั้นสัญญาว่าสำหรับฟังก์ชั่น async จะไม่ใช้ Bluebird เลยดังนั้นการที่ Bluebird ไม่ได้ช่วยในสถานการณ์นั้น
Adam Reis

คำตอบ:


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) ให้การติดตามสแต็กเต็มของข้อผิดพลาด
Adam Reis

ขอบคุณสำหรับการวางprocess.onแทนที่จะserver.onชอบในตัวอย่างอื่น ๆ อีกมากมายที่ฉันได้พบ
PhillipHolmes

9
ฉันหวังว่าฉันจะบอกว่ามันใช้งานได้ แต่มันก็ไม่ได้ ฉันใช้ Node 8.9.4
ffxsam

2
ฉันลองใช้โค้ดด้านบนและไม่ได้กำหนดทั้งเหตุผลและ p? ข้อเสนอแนะใด ๆ "Unhandled Rejection at: Promise {state: 'ปฏิเสธ', เหตุผล: undefined} เหตุผล: undefined"
Jeremy

3
ฉันเพิ่มรหัสนี้ที่ด้านบนของapp.jsไฟล์โหนดของฉันและไม่มีอะไรถูกบันทึกไว้อย่างน่าเสียดาย v10.13.0ปม
user1063287

71

ที่ถูกต้องวิธีการแสดงเต็มรูปแบบสำหรับ stacktrace unhandled ปฏิเสธ ES6 สัญญาคือการทำงาน Node.js กับ--trace-warningsธง สิ่งนี้จะแสดงสแต็คเทรซเต็มรูปแบบสำหรับทุกคำเตือนโดยไม่ต้องสกัดกั้นการปฏิเสธจากภายในโค้ดของคุณเอง ตัวอย่างเช่น:

ปม --trace-warnings app.js

ตรวจสอบให้แน่ใจว่าการtrace-warningsตั้งค่าสถานะมาก่อนชื่อ.jsไฟล์ของคุณ! มิฉะนั้นการตั้งค่าสถานะจะถูกตีความว่าเป็นข้อโต้แย้งสำหรับสคริปต์ของคุณและมันจะถูกละเว้นโดย Node.js เอง

หากคุณต้องการจัดการกับการปฏิเสธที่ไม่สามารถจัดการได้ (เช่นโดยการบันทึก) คุณอาจต้องการใช้unhandled-rejectionโมดูลของฉันแทนซึ่งจะจับการปฏิเสธที่ไม่ได้จัดการทั้งหมดสำหรับการใช้งานสัญญาที่สำคัญทุกรายการที่สนับสนุนด้วยการจัดการเหตุการณ์เดียว

โมดูลสนับสนุนครามสัญญา ES6, Q, WhenJS, es6-promise, then/promiseและสิ่งที่สอดคล้องกับใด ๆ ของข้อกำหนดการปฏิเสธไม่สามารถจัดการได้ (รายละเอียดในเอกสารประกอบ)


20
การใช้โหนด 7.8.0 และทั้งหมดนี้ทำให้ฉันคือการติดตามสแต็กสำหรับโมดูลโหนดภายในจำนวนมาก (โหนด: 10372) UnhandledPromiseRejectionWarning: การปฏิเสธสัญญาที่ไม่สามารถจัดการได้ (การปฏิเสธ id: 2): ไม่ได้กำหนดที่ emitWarning (ภายใน / กระบวนการ / contract.js: 59: 21) ที่ emitPendingUnhandledRejections (ภายใน / กระบวนการ / contract.js: 86: 11) ที่กระบวนการ ._tickDomainCallback (ภายใน / กระบวนการ / next_tick.js: 136: 7)
Will Lovett

3
ฉันไม่เห็นผลลัพธ์ใด ๆ ที่แสดงว่าปัญหาสัญญาที่ไม่สามารถจัดการได้อยู่ที่ใด
Jason Leach

ฉันได้เพิ่มสิ่งนี้เพื่อpackage.jsonเริ่มสคริปต์และไม่มีอะไรถูกบันทึกไว้อย่างน่าเสียดาย v10.13.0ปม
user1063287

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.