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
  • Mấy hôm trước OpenAI giới thiệu Deep Research - một công cụ duyệt web để nghiên cứu và cho ra một bản tổng hợp chỉ trong vài chục phút - so với nhiều giờ làm việc đối với con người, theo như họ công bố.

    Tính năng này hiện chỉ có sẵn cho người dùng Pro. Mặc dù chưa được dùng thử, nhưng qua nhiều bài viết đều nhấn mạnh vào sự ấn tượng trước khả năng của công cụ mới này. Nếu vẫn chưa biết Deep Research làm được gì thì bạn cứ hình dung như thế này: Nói với nó "Tôi cần thông tin nghiên cứu về lượng tiêu thụ cà phê của thế giới trong năm ngoái". Thế thôi! Ngồi chờ một lúc để nó tìm kiếm và tổng hợp lại kết quả và gửi lại cho bạn một bài báo cáo chi tiết. Chà, ghê thật chứ!

    Ngay lập tức huggingface đã lên một bài viết cố gắng tái tạo lại công cụ này theo cách của họ. Chi tiết tại Open-source DeepResearch – Freeing our search agents. Và không có gì ngạc nhiên khi cả 2 đều mang hơi hướng của AI Agents.

    » Xem thêm
  • Sống đủ lâu trong thế giới Internet, bạn có thể thấy rằng mọi người ở đây khá háo hức chạy theo xu hướng và chúng lan truyền với tốc độ chóng mặt.

    Chỉ vài tháng trước, chúng ta vẫn còn kinh ngạc về trí thông minh của các mô hình ngôn ngữ lớn (LLM) có thể trả lời giống như con người, và ngay sau đó, chúng đã được cập nhật với khả năng suy nghĩ và lý luận đáng kinh ngạc. Chúng được ứng dụng rộng rãi không chỉ trong lĩnh vực lập trình. Gần đây, thuật ngữ AI Agents đã tạo nên một sự khuấy động.

    Vậy, AI Agents là gì? Trong bài viết ngắn này, tất nhiên là không thể đưa ra một định nghĩa ngắn gọn nhưng toàn diện. Bạn đọc có thể tham khảo bài viết rất chi tiết này tại đây Agents | Chip Huyền. Để dễ hình dung hơn, AI Agents có thể được coi là một người hoặc một thực thể nào đó. Bản thân các Agents được trang bị tất cả các công cụ cần thiết. Từ đó, các Agents có thể kết hợp chúng để hoàn thành một nhiệm vụ mà chúng ta giao.

    Vẫn còn hơi mơ hồ phải không? Một ví dụ thực tế là khi bạn ra lệnh cho các Agents truy cập Facebook vào lúc 8 giờ tối mỗi ngày, kiểm tra bất kỳ tin tức nổi bật nào từ bạn bè, sau đó gửi tóm tắt đến Telegram. Vậy là xong!

    » Xem thêm
  • Hôm qua đến nay, lượt truy cập tới từ Facebook tăng đột biến. Thường như thế là do ai đó chia sẻ bài viết của blog vào một nhóm nào đó.

    Cơ mà lần này là liên kết trực tiếp đến trang chủ luôn. Tò mò ghê, không biết ai chia sẻ, chia sẻ ở đâu nữa. Muốn biết để tìm hiểu "insight" ghê 🥹

    » 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

Tôi & khao khát "chơi chữ"

Bạn đã thử viết? Và rồi thất bại hoặc chưa ưng ý? Tại 2coffee.dev chúng tôi đã có quãng thời gian chật vật với công việc viết. Đừng nản chí, vì giờ đây chúng tôi đã có cách giúp bạn. Hãy bấm vào để trở thành hội viên ngay!

Bạn đã thử viết? Và rồi thất bại hoặc chưa ưng ý? Tại 2coffee.dev chúng tôi đã có quãng thời gian chật vật với công việc viết. Đừng nản chí, vì giờ đây chúng tôi đã có cách giúp bạn. Hãy bấm vào để trở thành hội viên 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...
Bấm hoặc cuộn mạnh để sang bài mới