NodeJS bắt các ngoại lệ chưa được xử lý

Trong bài đăng này, tôi sẽ ghi lại một số ghi chú mà tôi đã thực hiện khi tái cấu trúc các quy trình xử lý ngoại lệ chưa được phát hiện trong Node. js. Hy vọng rằng nó có thể hữu ích cho những người khác quan tâm đến phần này của cơ sở mã hoặc cho các nhà khảo cổ mã trong tương lai

Lối thoát toàn cầu cho các trường hợp ngoại lệ chưa được phát hiện

Cốt lõi của việc xử lý ngoại lệ chưa được phát hiện trong Node. js hiện nằm trong

1
2
3
4
5
6
7
2 - tên này gần đây đã được đổi tên từ
1
2
3
4
5
6
7
3, tên này không còn là tên chính xác nữa vì các ngoại lệ được truyền cho nó không nhất thiết gây tử vong sau Node. js đã triển khai lối thoát hiểm
1
2
3
4
5
6
7
4 khoảng 10 năm trước

1
2
3
4
5
6
7
2 hiện tại về cơ bản thực hiện hai việc

  1. Lấy
    1
    2
    3
    4
    5
    6
    7
    6 từ đối tượng
    1
    2
    3
    4
    5
    6
    7
    7 và gọi nó
  2. Nếu
    1
    2
    3
    4
    5
    6
    7
    8 trả về true (e. g. khi người dùng đính kèm trình nghe
    1
    2
    3
    4
    5
    6
    7
    9), hãy tiếp tục thực hiện, nếu không thì in ngoại lệ ra thiết bị lỗi chuẩn, sau đó thoát khỏi Nút hiện tại. js (luồng công nhân hoặc luồng chính) với
    function run(er) {
    throw er; // the source line
    }

    const e = new Error('test');
    e.data = 1;
    run(e);
    0 (hoặc 1 nếu
    function run(er) {
    throw er; // the source line
    }

    const e = new Error('test');
    e.data = 1;
    run(e);
    0 không được đặt)

1
2
3
4
5
6
7
8 đã phát triển khá nhiều trong những năm qua, nhưng mục đích chính của nó vẫn là phát ra các sự kiện
1
2
3
4
5
6
7
9 cho người dùng

Cũng giống như nhiều thuộc tính khác có tiền tố là dấu gạch dưới,

1
2
3
4
5
6
7
8 là một chi tiết triển khai đã vô tình bị lộ cho người dùng - có lẽ nó không được dùng nữa vào thời điểm này

Những ngoại lệ chưa được phát hiện này đến từ đâu?

Hiện tại, có một số nơi có thể gọi

1
2
3
4
5
6
7
2

1. Trình nghe tin nhắn mỗi lần cô lập

trong nút. js, chỉ có một trình nghe thông báo cho mỗi lần cô lập được thêm vào thông qua

function run(er) {
throw er; // the source line
}

const e = new Error('test');
e.data = 1;
run(e);
6 cho mỗi V8 cô lập (mỗi Nút. js, phiên bản chính hoặc phiên bản worker, được liên kết với một phiên bản V8 riêng biệt). Khi có một ngoại lệ JavaScript được đưa ra (bởi người dùng hoặc bởi Node. js) trong vùng cô lập mà không bị bắt, V8 kích hoạt trình nghe đất C++ này và chúng tôi sẽ chuyển nó vào
1
2
3
4
5
6
7
2 để người dùng có cơ hội xử lý nó trong lối thoát toàn cầu

2. nội bộ C ++

Có một số nơi trong vùng đất C++ nơi

1
2
3
4
5
6
7
2 được gọi trực tiếp. trong nút. js gọi lại không đồng bộ thường được gọi bởi C++ khi một số hoạt động không đồng bộ được hoàn thành. Các cuộc gọi lại này không được phép tự đưa ra các ngoại lệ - thay vào đó, chúng được cho là chuyển các ngoại lệ xuống các cuộc gọi lại do người dùng cung cấp. Khi họ đưa ra các ngoại lệ không mong muốn (e. g. khi có lỗi), các ngoại lệ này được bắt bởi trình gọi C++, chuyển chúng xuống
1
2
3
4
5
6
7
2 để chúng có thể được xử lý kịp thời. Nó thường trông như thế này

1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
9

Lưu ý rằng

1
2
3
4
5
6
7
00 này không được dài dòng - nếu nó dài dòng, V8 sẽ gọi trình nghe thông báo per-isoolate với ngoại lệ đó, sau đó chúng ta sẽ xử lý cùng một ngoại lệ hai lần

3. nội bộ JavaScript

Cũng có thể kích hoạt

1
2
3
4
5
6
7
2 từ JavaScript bên trong của Node. js sử dụng
1
2
3
4
5
6
7
02 - về cơ bản chỉ là một ràng buộc nội bộ cho
1
2
3
4
5
6
7
2. Điều này được sử dụng để thực hiện e. g.
1
2
3
4
5
6
7
04, cho phép bạn nắm bắt các lời từ chối lời hứa chưa được xử lý trong sự kiện
1
2
3
4
5
6
7
9

Trong trường hợp bạn không nhận ra - hàng đợi tác vụ và quy trình xử lý lỗi trong Node. js hầu hết được triển khai bằng JavaScript, đó là lý do tại sao chúng tôi cần cung cấp quy trình này trong vùng đất JavaScript nội bộ

In ngoại lệ cho stderr với thông tin bổ sung

Nếu bạn chạy một tệp có tên

1
2
3
4
5
6
7
06 trông như thế này

1
2
3
4
5
6
7
function run(er) {
throw er; // the source line
}

const e = new Error('test');
e.data = 1;
run(e);

Khi trình nhúng không đính kèm trình nghe tin nhắn, theo mặc định, V8 sẽ in ngoại lệ chưa được phát hiện ra thiết bị xuất chuẩn với nội dung như thế này

1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0

Đó là nút. js có nhiệm vụ định dạng lại dấu vết ngăn xếp và in nội dung nào đó có nhiều thông tin hơn cho người dùng, như thế này

1
2
3
4
5
6
7
1
1
2
3
4
5
6
7
2

Làm thế nào nút. js tăng cường theo dõi ngăn xếp của một ngoại lệ nghiêm trọng

Theo dõi ngăn xếp nâng cao được trình bày ở trên bao gồm ít nhất 2 phần và 2 phần tùy chọn

1. Mã nguồn nơi xảy ra sự cố
1
2
3
4
5
6
7
07

1
2
3
4
5
6
7
4
1
2
3
4
5
6
7
5

Điều này có được thông qua

1
2
3
4
5
6
7
08, trong khi vị trí của mũi tên
1
2
3
4
5
6
7
09 được tính toán với nhiều phần bù khác nhau được thu thập từ API V8

2.
1
2
3
4
5
6
7
00

Theo mặc định,

1
2
3
4
5
6
7
00 bao gồm

  1. Kết quả của

    1
    2
    3
    4
    5
    6
    7
    02 được gọi trên ngoại lệ, trả về
    1
    2
    3
    4
    5
    6
    7
    03 và
    1
    2
    3
    4
    5
    6
    7
    04 chung bởi một dấu phẩy theo đặc điểm kỹ thuật ECMAScript

    1
    2
    3
    4
    5
    6
    7
    0____191
  2. Dấu vết ngăn xếp của nơi tạo ra ngoại lệ (lưu ý rằng điều này khác với nơi xảy ra

    1
    2
    3
    4
    5
    6
    7
    07)

    1
    2
    3
    4
    5
    6
    7
    1
    2
    3
    4
    5
    6
    7
    93

Có thể cho rằng, các khung bên trong bên dưới

1
2
3
4
5
6
7
06 không hoàn toàn hữu ích và có lẽ nên ẩn đi. Đối số truy cập trong Node. js cốt lõi là các báo cáo lỗi do người dùng gửi sẽ ít hữu ích hơn nếu các khung bên trong này bị ẩn theo mặc định. Nút. js hiện đang sử dụng màu mờ hơn để in các khung bên trong này khi thiết bị xuất chuẩn là TTY và điều đó làm giảm chi phí trực quan của các khung bên trong này ở một mức độ nhất định

Nút. js cũng thực hiện một số thủ thuật để cải thiện dấu vết ngăn xếp cho các đối tượng

1
2
3
4
5
6
7
07 được tạo nội bộ. Chẳng hạn, bạn có thể thấy
1
2
3
4
5
6
7
08 được đính kèm với tên của một Nút. js
1
2
3
4
5
6
7
07 (e. g. một được tạo bằng
1
2
3
4
5
6
7
10) trong dòng đầu tiên của dấu vết ngăn xếp

1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
95

Điều này được thực hiện bởi

  1. Nối mã
    1
    2
    3
    4
    5
    6
    7
    11 vào thuộc tính
    1
    2
    3
    4
    5
    6
    7
    03 để nó xuất hiện trong dòng thông báo của dấu vết ngăn xếp
  2. Lưu
    1
    2
    3
    4
    5
    6
    7
    00 (trong v8
    1
    2
    3
    4
    5
    6
    7
    00 được tạo một cách lười biếng và được duy trì sau khi truy cập)
  3. Khôi phục
    1
    2
    3
    4
    5
    6
    7
    03 thành
    1
    2
    3
    4
    5
    6
    7
    16

Nút. js đã từng để lại mã trong

1
2
3
4
5
6
7
03 nhưng hành vi này đã được thay đổi để khớp với tên lỗi trên Web và để cho phép người dùng sử dụng tên rõ ràng hơn

Định dạng của

1
2
3
4
5
6
7
00 có thể được thay đổi bởi người dùng bằng hook
1
2
3
4
5
6
7
19 toàn cầu, đây là API V8 hiện đã được điền đầy bởi Node. js với một số quirks đáng tiếc được duy trì. Kể từ nút. js thực hiện cải tiến sau khi tạo
1
2
3
4
5
6
7
00, hãy cẩn thận rằng nó có thể không phát cùng với
1
2
3
4
5
6
7
19 do người dùng xác định

3. (tùy chọn) Thuộc tính bổ sung trên đối tượng
1
2
3
4
5
6
7
07

Khi có thêm các thuộc tính đếm được trên đối tượng

1
2
3
4
5
6
7
07, chẳng hạn như
1
2
3
4
5
6
7
08, chúng sẽ được hiển thị bằng định dạng tương tự như đầu ra của
1
2
3
4
5
6
7
25

1
2
3
4
5
6
7
4
1
2
3
4
5
6
7
97

Trên thực tế, 2 và 3 đều là một phần của đầu ra của

1
2
3
4
5
6
7
26, bởi vì đó là những gì Node. js sử dụng để in các ngoại lệ

4. (tùy chọn) cải tiến cho các trường hợp ngoại lệ được phát ra trên các
1
2
3
4
5
6
7
27

Nếu ngoại lệ gây tử vong vì nó được phát ra trên phiên bản

1
2
3
4
5
6
7
27 nhưng không được xử lý, Node. js hiện cũng hiển thị nơi nó được phát ra. Ví dụ: khi bạn chạy một đoạn mã như thế này

1
2
3
4
5
6
7
4
1
2
3
4
5
6
7
99

Nút. js sẽ thoát với nội dung như thế này được in ra thiết bị lỗi chuẩn

1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
1

Dấu vết ngăn xếp đầu tiên cho bạn biết nơi ngoại lệ được tạo, trong khi ngăn xếp thứ hai cho bạn biết nơi ngoại lệ được phát ra. Dấu vết ngăn xếp thứ hai được lưu trong cuộc gọi của

1
2
3
4
5
6
7
29 và được hiển thị khi Nút. js phát hiện ra rằng ngoại lệ nghiêm trọng đi kèm với một số thông tin đã lưu - tất nhiên, điều này đi kèm với một chút chi phí, nhưng nó khá hữu ích khi gỡ lỗi các loại ngoại lệ này

Thông báo cho thanh tra

Ngoài việc in các ngoại lệ cho stderr, Node. js cũng cần thông báo cho trình kiểm tra V8 về các ngoại lệ này bằng cách gọi

1
2
3
4
5
6
7
40 - theo mặc định, điều này khiến trình kiểm tra ghi nhật ký các ngoại lệ trong bảng điều khiển

Các cải tiến nói trên thực sự được chia thành hai giai đoạn dựa trên thời điểm người kiểm tra được thông báo. Chẳng hạn, chúng tôi chỉ thêm mã màu ANSI vào dấu vết ngăn xếp sau khi trình kiểm tra hiển thị chúng, vì ứng dụng khách của trình kiểm tra (e. g. Chrome DevTools) có thể cách điệu ngoại lệ theo cách khác và chúng không nhất thiết phải nhận ra mã màu

Tóm lược

Quy trình xử lý ngoại lệ hiện tại trong Node. js đến từ sự làm việc chăm chỉ của nhiều người. Không phải mọi phần của nó đều là lựa chọn tốt nhất khi nhìn lại và nó vẫn liên tục quay vòng, nhưng nhìn vào mã đằng sau nó (và thật ngạc nhiên là có rất nhiều mã) khiến tôi đánh giá cao công việc từ Node. những người đóng góp js trong những năm qua thậm chí còn nhiều hơn nữa

Cách tốt nhất để xử lý các lỗi logic trong NodeJS là gì?

Đối tượng lỗi
Cố gắng bắt
Ném
ngăn xếp cuộc gọi
Đặt tên hàm hiệu quả
Các mô hình không đồng bộ như lời hứa

Cách tốt nhất có thể để xử lý ngoại lệ như vậy với miền NodeJS bằng express là gì?

Cách giải quyết là thêm khối try/catch của riêng bạn vào "gốc" mà sau đó bạn có thể sử dụng để phát ra sự kiện "lỗi" cho miền trước khi kết nối . .

Sử dụng try catch trong NodeJS có tốt không?

Ghi chú. Đó là một cách thực hành tốt để sử dụng Node. js Chỉ thử Catch cho các hoạt động đồng bộ . Chúng ta cũng sẽ tìm hiểu trong hướng dẫn này về lý do không nên sử dụng Try Catch cho các hoạt động không đồng bộ.

Làm cách nào để tạo trình xử lý lỗi toàn cầu trong NodeJS?

Bước 1 — Tạo ứng dụng cấp tốc. Tạo ứng dụng cấp tốc
Bước 2 — Tạo và thêm phần mềm trung gian xử lý lỗi và triển khai phần mềm này. phần mềm trung gian xử lý lỗi
Bước 3 — Ném lỗi từ ứng dụng để kiểm tra mã của chúng tôi. Ném lỗi
Bước 3— Gọi phương thức gửi của lớp cơ sở bằng siêu từ khóa