Cách xử lý error trong ứng dụng Express và NodeJS


1057

Lời mở đầu

Khi chúng ta tạo API với Express và NodeJS, xác định các routes và trình handlers của chúng. Trong thế giới perfect, API chỉ đưa ra request đến các route mà đã xác định . Và các route sẽ hoạt động mà không có lỗi. Nhưng nếu bạn để ý, chúng ta không sống trong một thế giới lý tưởng :). Express biết điều này và giúp việc xử lý các lỗi trong API trở nên dễ dàng.

Kham thảo thêm API tại đây : 10 cách để viết restful api NodeJS chuẩn cơm mẹ nấu luôn

Trong bài viết này, tôi sẽ giải thích cách xử lý error trong Express. Để làm theo bạ nên sao chép clone lưu trữ này. Hãy nhớ cài đặt npm sau khi sao chép repo.

Kho lưu trữ có một tệp JavaScript duy nhất, index.js với nội dung sau


const express = require("express");
const app = express();
const port = 3000;
app.get("/", (req, res, next) => {
 res.send("Welcome to main route!");
});
app.get("/about", (req, res, next) => {
 res.send("This is the about route!");
});
app.listen(port, () => console.log(`App listening on port: ${port}`));

Nếu bạn không muốn sao chép repo. Hãy tạo một thư mục mới, npm init -y và sau đó npm i –save express. Tạo index.js trong thư mục này và copy code vào đó.

Sources của error

Có hai cách cơ bản để xảy ra lỗi trong ứng dụng Express.

Cách đầu tiên là khi request được thực hiện đến một đường dẫn mà không có trình xử lý route nào được xác định cho nó. Ví dụ, index.js xác định 2 get route (1 . ‘/’ và 2 ‘/about’). Tôi đang sử dụng get routes để có thể dễ dàng kiểm tra các route trong trình duyệt. Lưu ý rằng một route xác định path  và một middleware sẽ được gọi khi có request đến path đó:

app.HTTPMethod(path, middleware)
// HTTPMethod = get, post, put, delete …

Một nguồn lỗi khác là khi có sự cố xảy ra trong trình xử lý route hoặc bất kỳ nơi nào khác trong code. Ví dụ: cập nhật route đầu tiên trong `index.js` như sau:

…
app.get(‘/’, (req, res, next) => {
 // mimic an error by throwing an error to break the app!
 throw new Error(‘Something went wrong’);
 res.send(‘Welcome to main route!’)
})
…

Khởi động lại server và truy cập localhost: 3000, bạn sẽ được chào đón với một lỗi và một stacktrace.

Xử lý error router bằng cách sắp xếp chúng

Loại bỏ câu lệnh throws trong index.js. Khởi động máy chủ và truy cập localhost: 3000 trong trình duyệt, bạn sẽ thấy thông báo:

Welcome to the main route!

Truy cập localhost: 3000 /about:

This is the about route!

Làm thế nào để Express tra cứu các route?

Express tạo ra thứ được gọi là routing table, nơi đó đặt các route theo thứ tự mà chúng đã được xác định trong code. Khi một request đến server web, URI được chạy qua routing table và kết quả phù hợp đầu tiên trong table được sử dụng – ngay cả khi có nhiều hơn một kết quả phù hợp.

Nếu không tìm thấy kết quả phù hợp nào thì Express sẽ hiển thị lỗi. Để xem hoạt động này, hãy truy cập localhost: 3000 / contact, trình duyệt hiển thị:

Cannot GET /contact

Sau khi kiểm tra routing table, Express không tìm thấy kết quả phù hợp với /contact, vì vậy nó respond với error.

Cách khai thác thứ tự các route

Vì Express hiển thị thông báo lỗi khi không tìm thấy kết quả phù hợp nào cho một URI nhất định trong routing table, điều này có nghĩa là chúng taxác định một route để xử lý error bằng cách đảm bảo rằng route này là route cuối cùng trên routing table. Đường dẫn error nên phù hợp với route trên NodeJS

Bởi vì chúng ta không biết path không tồn tại mà người dùng sẽ request, chúng ta không thể hardcode một đường dẫn vào route error này. Chúng ta cũng không biết request có thể sử dụng phương thức HTTP nào, do đó sử dụng app.use () thay vì app.get.

Thêm code vào file index.js bằng cách đặt route sau vào cuối khai báo route, trước app.listen ():

…
// this matches all routes and all methods
app.use((req, res, next) => {
 res.status(404).send({
 status: 404,
 error: ‘Not found’
 })
})app.listen(port …

Khởi động lại máy chủ và truy cập một route không được xác định, ví dụ: localhost: 3000 / blog

Bây giờ, chúng ta có một response error tùy chỉnh:

{“status”:404,”error”:”Not found”}

Hãy nhớ rằng thứ tự của các route là rất quan trọng để điều này hoạt động. Nếu route xử lý lỗi này nằm ở đầu khai báo route thì mọi đường dẫn – hợp lệ và không hợp lệ – sẽ được khớp với nó. Chúng ta không muốn điều này, vì vậy route xử lý lỗi phải được xác định sau cùng trong app NodeJS.

Xử lý bất kỳ loại error nào

Giải pháp từ phần trước hoạt động nếu chúng ta chỉ muốn xử lý lỗi từ các requests đến route không tồn tại. Nhưng nó không xử lý các lỗi khác có thể xảy ra trong ứng dụng và đó là cách xử lý lỗi không hoàn chỉnh. Nó chỉ giải quyết được một nửa vấn đề trong app NodeJS

Thêm đoạn code sau vào index.js để xử lý lỗi trong route get đầu tiên:

…
app.get(‘/’, (req, res, next) => {
 throw new Error(‘Something went wrong!’);
 res.send(‘Welcome to main route!’)
})
…

Nếu bạn truy cập localhost: 3000, bạn vẫn sẽ thấy response của trình xử lý error mặc định Express.

Xác định xử lý error ở middleware

Các middleware xử lý lỗi được khai báo giống như các function middleware khác, ngoại trừ việc chúng có bốn argument thay vì ba. Ví dụ:

// error handler middleware
app.use((error, req, res, next) => {
 console.error(error.stack);
 res.status(500).send(‘Something Broke!’);
})

Đặt code này sau khai báo route trong index.js trước app.listen. Và sau app.use đầu tiên, khởi động lại server rồi truy cập localhost: 3000. Bây giờ response là:

Something Broke!

Bây giờ, chúng ta đang xử lý cả hai loại lỗi. Aha!

Điều này hiệu quả nhưng chúng ta có thể cải thiện nó không? Chắc chắn có. và làm như thế nào?

Khi bạn chuyển một argument tới next (), Express sẽ cho rằng đây là error và nó sẽ bỏ qua tất cả các route khác. Và gửi bất cứ thứ gì đã được chuyển đến next () tới middleware xử lý lỗi đã được xác định.

Chỉnh sửa file index.js như sau

…
app.use((req, res, next) => {
 const error = new Error(“Not found”);
 error.status = 404;
 next(error);
});// error handler middleware
app.use((error, req, res, next) => {
  res.status(error.status || 500).send({
   error: {
   status: error.status || 500,
   message: error.message || ‘Internal Server Error’,
  },
 });
});
…

Function middleware xử lý request xấu hiện được chuyển giao cho middleware xử lý lỗi. next (error) ngụ ý: ‘Này, Ngài xử lý lỗi, Tôi gặp lỗi, hãy xử lý nó!’.

Để đảm bảo rằng bạn đang ở trên cùng một trang với tôi, lỗi dòng.status || 500 ngụ ý rằng nếu đối tượng lỗi không có thuộc tính trạng thái, chúng ta sử dụng 500 làm code trạng thái. Nội dung đầy đủ của index.js là:

const express = require("express");
const app = express();
const port = 3000;
app.get("/", (req, res, next) => {
  throw new Error("Something went wrong!");
  res.send("Welcome to main route!");
});
app.get("/about", (req, res, next) => {
  res.send("This is the about route!");
});
app.use((req, res, next) => {
  const error = new Error("Not found");
  error.status = 404;
  next(error);
});
// error handler middleware
app.use((error, req, res, next) => {
    res.status(error.status || 500).send({
      error: {
        status: error.status || 500,
        message: error.message || 'Internal Server Error',
      },
    });
  });
app.listen(port, () => console.log(`App listening on port: ${port}`));

Nếu bạn đang cung cấp các trang tĩnh thay vì gửi response JSON, thì logic vẫn giống nhau. Bạn chỉ cần thay đổi những gì xảy ra trong trình xử lý lỗi. Ví dụ:

app.use((error, req, res, next) => {
 console.error(error); // log an error
 res.render(‘errorPage’) // Renders an error page to user!
});

Nếu bạn thấy bài viết này hữu ích, vui lòng chia sẻ với bạn bè và những người theo dõi của bạn và xem các bài viết khác của tôi. ^^

Kết luận

Qua bài viết, chúng ta đã biết thêm về cách xử lý error trong ứng dụng Express và NodeJS

Tham khảo thêm về NodeJS : 3 package NodeJS hữu ích bạn nên thử

Và tham khảo thêm về React :


Like it? Share with your friends!

1057