Bên cạnh xử lý lỗi, tạo ra lỗi bằng đối tượng Error cũng không kém phần quan trọng

Bên cạnh xử lý lỗi, tạo ra lỗi bằng đối tượng Error cũng không kém phần quan trọng

Tin ngắn hàng ngày dành cho bạn
  • Manus đã chính thức mở cửa cho tất cả người dùng rồi đấy mọi người. Cho những ai chưa biết thì đây là một công cụ viết báo cáo (làm mưa làm gió) giống như Deep Research của OpenAI á. Mỗi ngày được miễn phí 300 Credits để nghiên cứu. Mỗi lượt nghiên cứu tiêu tốn tuỳ thuộc vào độ phức tạp của yêu cầu. À với cả họ đang có chương trình tặng miễn phí Credits hay sao á. Như mình thì vào thấy được hẳn 2000.

    Mình dùng thử, so sánh với cùng một lệnh giống như đợt trước dùng bên Deep Research thì nội dung khác biệt nhau hoàn toàn. Manus báo cáo như kiểu viết văn hơn so với OpenAI là các gạch đầu dòng và bảng biểu.

    À lúc đăng ký xong có bắt nhập số điện thoại để xác minh, nếu lỗi thì các bạn đợi qua ngày thử lại xem có được không nhé.

    » Xem thêm
  • Mọi người chắc nghe nhiều về xu hướng tìm kiếm thông tin bằng AI chứ không cần công cụ tìm kiếm như Google nữa rồi đúng không? Không đâu xa ánh xạ vào bản thân thì thấy đúng thật, thi thoảng mới tìm kiếm thôi chứ còn đâu toàn hỏi tụi AI.

    Ngay từ đầu viết blog, thứ mà mình hướng đến là chia sẻ kinh nghiệm chứ không phải là những bài mang nặng tính kỹ thuật, máy móc, hướng dẫn từ đầu... Vì thời điểm đó đã có quá nhiều người làm nội dung này rồi và họ làm rất tốt, tại sao mình phải cố phát minh lại bánh xe? Một điều nữa là tin tưởng độc giả của mình có khả năng tìm hiểu vấn đề. Nếu bạn đọc đủ nhiều các bài viết trên blog thì thấy mình luôn cố gắng chèn thêm các liên kết tham khảo ngoài bài viết, nêu ra vấn đề mở và rất ít khi kết luận chắc chắn một điều gì đó.

    Mình đã cố gắng rèn luyện kỹ năng viết, kỹ năng trình bày và cả cách tương tác với độc giả để mang lại giá trị cho họ. Nhiều lúc ngồi lật lại các con số thống kê thấy lượng đọc bài viết tăng lên lại cảm thấy vui. Nhưng khi nguồn truy cập đến từ Google thì lại thấy buồn, vì điều đó chứng tỏ họ biết đến mình chỉ khi đang cố đi tìm giải pháp, có thể họ chỉ đọc chớp nhoáng, may ra tìm được cách giải quyết và thế là đóng cửa sổ trình duyệt rồi đi như một cơn gió.

    Chừng vài tháng đổ lại đây, một điều khiến mình rất vui đó là lượng người truy cập thẳng vào trang chủ mà không thông qua công cụ tìm kiếm đang tăng dần lên, có nhiều hôm lượng truy cập tự nhiên còn cao hơn cả đến từ Google. Điều đó chứng tỏ độc giả đã có thói quen quay lại trang của mình nhiều hơn và họ tìm thấy được giá trị từ blog mang lại. Vui mừng khôn xiết 🤩

    Bên cạnh đó thì lượng truy cập vào chuyên mục Threads - tức là mục mình đang viết bài này đang cao hơn bao giờ hết. Điều đó chứng tỏ xu hướng đi theo tin nhanh là đúng đắn. Mình có thể ngồi cả ngày để viết tin ngắn cho bạn đọc vì nó rất nhanh mà tiện, không tốn công đi tìm tài liệu để viết, không tốn cả thời gian viết nữa, còn mình thì có rất nhiều thứ để chia sẻ 😅. Nhưng không vì thế mà bỏ bê các bài viết dài, vì dài thì có nhiều thông tin để chia sẻ hơn.

    Vài lời tâm sự thế thôi chứ hơn một tháng nay mình chưa viết bài viết mới nào vì công việc bận quá. Xong lâu dần cứ trì hoãn lại thành lười. À với cả tháng 5 này rất thích hợp để đọc các cuốn sách về cách mạng á. Có hôm đọc đến 2 giờ sáng mới đi ngủ 🥱

    » Xem thêm
  • Mình mới nhìn thấy một trang web khá thú vị nói về các cột mốc đáng nhớ trong lịch sử phát triển Internet toàn cầu: Internet Artifacts

    Chỉ từ 1977 - khi Internet còn nằm trong hộp thí nghiệm thì nhìn xem - giờ đây Internet đã khiến mọi thứ phát triển đến mức nào 🫣

    » Xem thêm

Vấn đề

Cách đây khá lâu tôi có một bài viết nói về Một số phương pháp xử lý lỗi (error handling) trong Node.js, nội dung trong bài xoay quanh việc làm thế nào để bắt được lỗi và xử lý chúng một cách dễ dàng. Trong bài viết này, tạm thời bỏ qua những phương pháp đó, chúng ta hãy đi sâu vào phân tích việc "đẩy" ra lỗi và làm sao để "bắt" được chúng.

Tôi cá là có nhiều người, trong đó có cả tôi từng đẩy ra một lỗi trông giống như thế này:

function login(username, password) {
  // code
  if (password != hash_password) {
    throw new Error("Password is incorrect");
  }
// code
}

Sau đó "bắt" lỗi:

try {
  login("admin", "123456");
} catch(e) {
  console.log(e.message);
  // logic handle
}

Chẳng có gì nhiều để bàn đến cách xử lý lỗi ở trên cả, khi "đẩy" ra một Error, nó sẽ mang theo rất nhiều thông tin hữu ích gây ra lỗi như vị trí (stack trace) và thông tin lỗi (message). Vì thế cho nên e ở trong catch(e) giúp ta dễ dàng truy ra được nguồn gốc lỗi để từ đó xử lý sao cho hợp lý.

Tôi từng gặp trường hợp đẩy ra một lỗi không đúng cách, thay vì new Error, lại đẩy ra một chuỗi hay một đối tượng. Giống như là:

throw 'Password is incorrect';

Với cách này, chúng ta vẫn có thể try catch. Tuy nhiên, e lúc này chỉ đơn giản là một chuỗi hoặc một đối tượng mà bạn đã đẩy ra trước đó, nó không chứa những thông tin quan trọng như stack trace và message như của Error. Chính vì thế, bất cứ khi nào đẩy ra một lỗi, hãy biến nó thành một instance của Error.

Error chỉ nhận vào tham số là một chuỗi, nó cũng chính là nội dung củae.message. Nếu ta cố tình truyền vào nhiều hơn một tham số hoặc tham số là một thứ gì đó khác string như object thì sẽ gây ra một hiện tượng giống như dưới đây:

throw new Error({ "name": "2coffee" });

VM400:1 Uncaught Error: [object Object]
    at <anonymous>:1:7

Sở dĩ tôi nêu ra vấn đề này vì có nhiều trường hợp, chúng ta cần thêm nhiều thông tin được vào trong một lỗi để tiện cho việc xử lý logic nào đó. Giả dụ như bên cạnh message, tôi cần thêm uuid là id của bản ghi gây ra lỗi, detail chứa một mô tả chi tiết hơn, code để chỉ định mã lỗi được định nghĩa trong hệ thống... thì với Error, hoàn toàn là không được.

Vậy có cách nào làm được điều này không?

Errors Class

Error là một đối tượng bị "đẩy" ra khi xảy ra lỗi trong thời gian chạy (runtime error). Error cũng có thể được sử dụng để làm đối tượng cơ sở cho các lỗi do người dùng xác định. Hay nói một cách dân dã là có thể tạo ra một Class kế thừa Error để tạo ra một đối tượng lỗi cho riêng mình.

JavaScript cung cấp một số đối tượng lỗi "tùy chỉnh" khác dựa trên Error mà có thể bạn đã từng gặp rất nhiều rồi như:

Để xem danh sách đầy đủ Error types, bạn đọc tham khảo tại Error types - Mozilla.

Điểm chung là chúng dựa trên Error nên mang đầy đủ thuộc tính quan trọng của Error. Ngoài ra, các lỗi này còn mang một sự minh bạch trong mã của bạn. Ví dụ khi đẩy ra một lỗi RangeError chúng ta có thể biết lỗi là do một giá trị nào đó nằm ngoài giá trị cho phép, thay vì throw new Error('The argument must be between 1 and 10') một cách chung chung.

Để phân biệt các đối tượng lỗi, chỉ cần thông qua các câu lệnh điều kiện như if...else, switch...case...

if (err instanceof RangeError) {
  // handle RangeError
} else if (err instanceof ReferenceError) {
  // handle TypeError
}
...

Các đối tượng lỗi tùy chỉnh này cũng tương tự như Error, chỉ khác mỗi name. Do đó nếu cần một lỗi "khác biệt" hơn, hãy chuyển sang phần tiếp theo.

Custom Errors Class

Chúng ta có thể tự xác định các loại lỗi của riêng mình bằng cách kế thừa từ Error. Sau đó, đẩy ra lỗi bằng cách throw MyError và sử dụng instanceof MyError để kiểm tra loại lỗi trong catch. Điều này dẫn đến các đoạn mã xử lý lỗi sạch sẽ và nhất quán hơn.

Cú pháp đơn giản nhất để tạo ra một MyError lỗi tùy chỉnh:

class MyError extends Error {
  constructor(message) {
    super(message);
    this.name = this.constructor.name;
  }
}

MyError lúc này được gán name bằng constructor.name cũng chính là cái tên MyError của class. Tuy vậy, nó chưa có nhiều khác biệt gì so với Error thông thường, chỉ khác mỗi name. Chúng ta cần thêm một vài thuộc tính như code là mã lỗi và statusCode để định nghĩa cho HTTP response status codes.

class MyError extends Error {
  code;
  statusCode;

  constructor(message, code, statusCode) {
    super(message);
    this.name = this.constructor.name;
    this.code = code;
    this.statusCode = statusCode;
  }
}

Để đẩy ra lỗi, sử dụng cú pháp throw MyError:

try {
  throw new MyError("My error message", 123, 404);
} catch (err) {
  console.log(err.name, err.message, err.code, err.statusCode);
  // MyError My error message 123 404
}

Dựa vào tính năng này, có thể tạo ra nhiều lỗi riêng cho mình để phục vụ cho mục đích xử lý. Ví dụ, tạo ra class ApplicationError, DatabaseError, ValidateError... có các tính năng tương tương với lỗi hệ thống, lỗi cơ sở dữ liệu, lỗi xác thực dữ liệu... để từ đó ẩn hoặc hiện thông báo lỗi cho người dùng.

Tổng kết

Error là một đối tượng để xử lý lỗi trong chương trình viết bằng JavaScript. Cách tốt nhất để đẩy ra một lỗi là đẩy ra một Error thay vì chuỗi hoặc một đối tượng khác. JavaScript định nghĩa sẵn một vài "kiểu" lỗi dựa trên Error như ReferenceError, SyntaxError, RangeError... Ngoài ra, có thể tự tạo kiểu lỗi cho riêng mình bằng cách kế thừa từ Error.

Tài liệu tham khảo:

Cao cấp
Hello

Bí mật ngăn xếp của Blog

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.

Bình luận (0)

Nội dung bình luận...