Làm cách nào để tìm thấy những lời hứa nào chưa được xử lý trong Node.js UnhandledPromiseRejectionWarning?


177

Node.js từ phiên bản 7 có async / đang chờ đường cú pháp để xử lý các lời hứa và bây giờ trong mã của tôi, cảnh báo sau xuất hiện khá thường xuyên:

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

Thật không may, không có tham chiếu đến dòng bị thiếu. Có cách nào để tìm thấy nó mà không cần kiểm tra mọi khối thử / bắt không?


Bạn có thể sử dụng thư viện lời hứa Bluebird và nó có thể sẽ cung cấp cho bạn dấu vết ngăn xếp.
jfriend00

3
Có lẽ đăng ký vào unhandledRejectionsự kiện của Node sẽ giúp? Xem tài liệu . Cuộc gọi lại của bạn có được Errorđối tượng và thực tế Promisevà tôi tin rằng Errorđối tượng có thể giữ dấu vết ngăn xếp.
YSK

Nếu hai bình luận trước không có ích, thì Can't set headers after they are sent.sẽ cung cấp cho bạn manh mối về mã trong đó có thể xảy ra (nghĩa là bạn đang đặt tiêu đề sau khi các tiêu đề đã được gửi - có lẽ do không hiểu được mã không đồng bộ , nhưng đó là một phỏng đoán)
Jaromanda X

hi rằng các thông báo giúp chắc chắn trong việc tìm ra lỗi trong mã, btw không dễ như biết dòng.
1658162

1
@ jfriend00 Hóa ra đó là tình huống mà một hàm async đang gặp lỗi - những lời hứa Node nội bộ đó cho các hàm async không sử dụng Bluebird, vì vậy, có Bluebird không giúp ích gì trong kịch bản đó.
Adam Reis

Câu trả lời:


297

lắng nghe unhandledRejectionsự kiện của quá trình.

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
Ghi nhật ký error.stack(hoặc trong ví dụ trên reason.stack) cung cấp cho bạn dấu vết ngăn xếp đầy đủ của lỗi.
Adam Reis

Cảm ơn bạn đã đặt process.onthay vì server.onthích trong rất nhiều ví dụ khác mà tôi đã tìm thấy
PhillipHolmes

9
Tôi ước tôi có thể nói điều này làm việc, nhưng nó không. Tôi đang ở trên Node 8.9.4.
ffxsam

2
Tôi đã thử mã trên và không xác định được cả hai lý do, và p? Bất kỳ đề xuất? "Từ chối chưa được xử lý tại: Promise {state: 'bị từ chối', lý do: không xác định} lý do: không xác định"
Jeremy

3
Tôi đã thêm mã này vào đầu app.jstệp nút của mình và không có gì đáng tiếc được ghi lại. Nút v10.13.0.
dùng1063287

71

Cách chính xác để hiển thị một ngăn xếp đầy đủ cho các lần từ chối ES6 chưa được xử lý, là chạy Node.js với --trace-warningscờ. Điều này sẽ hiển thị stacktrace đầy đủ cho mọi cảnh báo, mà không phải chặn từ chối từ trong mã của riêng bạn. Ví dụ:

nút --trace-cảnh báo app.js

Đảm bảo rằng trace-warningscờ xuất hiện trước tên .jstệp của bạn ! Mặt khác, cờ sẽ được hiểu là đối số cho tập lệnh của bạn và nó sẽ bị chính Node.js bỏ qua.

Nếu bạn thực sự muốn xử lý các từ chối chưa được xử lý (ví dụ: bằng cách đăng nhập chúng), thì bạn có thể muốn sử dụng unhandled-rejectionmô-đun của tôi để thay thế tất cả các từ chối chưa xử lý cho mọi triển khai Promise chính hỗ trợ nó, với một trình xử lý sự kiện duy nhất.

Đó là mô-đun hỗ trợ Bluebird, Promises ES6, Q, WhenJS, es6-promise, then/promise, và bất cứ điều gì mà phù hợp với bất kỳ của các chi tiết kỹ thuật từ chối không được quản lý (đầy đủ chi tiết trong tài liệu).


20
Sử dụng nút 7.8.0 và tất cả những điều này mang lại cho tôi là một dấu vết ngăn xếp cho một loạt các mô-đun nút bên trong. (nút: 10372) Chưa xác địnhPromiseRejectionWarning: Từ chối lời hứa chưa được xử lý ._tickDomainCallback (nội bộ / quy trình / next_tick.js: 136: 7)
Will Lovett

3
Tôi không thấy bất kỳ đầu ra nào cho thấy vấn đề về lời hứa chưa được giải quyết.
Jason Leach

Tôi đã thêm phần này để package.jsonbắt đầu tập lệnh và không có gì đáng tiếc được ghi lại. Nút v10.13.0.
dùng1063287

1
@ user1063287 Đảm bảo rằng cờ ở đúng vị trí trong lệnh của bạn. Tôi vừa thêm một bản cập nhật cho câu trả lời, để nhấn mạnh rằng nó cần phải đi trước tên tập lệnh.
Sven Slootweg

2
Bạn có thể đang nhìn vào dấu vết ngăn xếp của cảnh báo khấu hao, không phải là lỗi chưa được xử lý ban đầu (phải ở đâu đó trên cảnh báo khấu hao).
Sven Slootweg

7

Đăng nhập với dấu vết ngăn xếp

Nếu bạn đang tìm kiếm thêm một thông báo lỗi hữu ích. Hãy thử thêm nó vào tập tin nút của bạn. Nó sẽ hiển thị theo dõi ngăn xếp đầy đủ nơi xảy ra sự cố của bạn.

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

Sự khác biệt duy nhất về chức năng là thực hiện console.dir trên thuộc tính ngăn xếp của lỗi. Khá khác biệt về sản lượng so với câu trả lời được chấp nhận.
joshuakcockrell
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.