Log chỉ còn “Không đọc được cấu hình”, trong khi lỗi ban đầu đã bị bỏ mất khi ném một Error mới. Một thông báo có ngữ cảnh giúp biết thao tác nào thất bại, nhưng vẫn cần giữ nguyên nguyên nhân để điều tra. Error.cause cho phép liên kết hai lớp thông tin này.
Bài viết dùng dữ liệu local và không gửi log ra dịch vụ ngoài. Các ví dụ áp dụng trên runtime hỗ trợ tùy chọn cause của Error; cần kiểm tra phiên bản Node.js hoặc trình duyệt mà ứng dụng thực sự sử dụng.
1. Giữ tham chiếu tới lỗi ban đầu
const original = new SyntaxError('Invalid configuration text');
const contextual = new Error('Could not load configuration', {
cause: original
});
console.log(contextual.message); // Could not load configuration
console.log(contextual.cause === original); // true
console.log(contextual.cause.name); // SyntaxError
Object lỗi gốc vẫn được giữ qua cause. Thông báo ngoài mô tả thao tác; lỗi trong cung cấp chi tiết ở điểm thất bại. Không cần nối toàn bộ stack vào message chỉ để tạo liên kết giữa hai lỗi.
Nếu tầng hiện tại không bổ sung ngữ cảnh hữu ích, có thể ném lại chính lỗi nhận được. Bọc lỗi tại mọi hàm bằng cùng thông báo chung chỉ làm chuỗi nguyên nhân dài hơn mà ít giá trị hơn.
2. Bọc ở ranh giới thao tác có ý nghĩa
function readConfigText(text) {
if (typeof text !== 'string') {
throw new TypeError('Expected configuration text');
}
try {
return JSON.parse(text);
} catch (cause) {
throw new Error('Configuration JSON could not be parsed', { cause });
}
}
try {
readConfigText('{');
} catch (error) {
console.log(error.message); // Configuration JSON could not be parsed
console.log(error.cause instanceof SyntaxError); // true
}
Đặt tên hàm theo đúng phạm vi: nó đọc cú pháp JSON, chưa kiểm tra schema cấu hình. JSON hợp lệ như null hoặc một mảng vẫn có thể được trả về. Trường bắt buộc, kiểu và miền giá trị cần được xác nhận ở bước riêng.
Ví dụ không chèn nội dung cấu hình vào message vì dữ liệu thực tế có thể chứa thông tin không phù hợp để ghi log. Để điều tra, bổ sung mã thao tác hoặc correlation ID theo chính sách hệ thống thay vì mặc định lưu toàn bộ đầu vào.
3. cause không bắt buộc là một Error
const failure = new Error('Import failed', {
cause: { code: 'INVALID_ROW', row: 4 }
});
console.log(failure.cause instanceof Error); // false
console.log(failure.cause.code); // INVALID_ROW
console.log(failure.cause.row); // 4
Cause có thể chứa dữ liệu cấu trúc có chủ đích. Nó cũng có thể là chuỗi, null hoặc giá trị khác do một thư viện ném ra. Đừng mặc định error.cause.message luôn tồn tại ở mọi catch.
Nếu cần mã lỗi ổn định để phân nhánh, hãy công bố cấu trúc mã trong contract thay vì phân tích chuỗi message. Khi nhận lỗi từ nguồn không kiểm soát, kiểm tra kiểu trước khi đọc trường và chỉ lấy các thông tin cần thiết.
4. JSON.stringify không tự xuất đầy đủ thông tin lỗi
const original = new Error('Parse failed');
const error = new Error('Load failed', { cause: original });
console.log(JSON.stringify(error)); // {}
const record = {
name: error.name,
message: error.message,
causeName: error.cause instanceof Error ? error.cause.name : null
};
console.log(JSON.stringify(record));
// {"name":"Error","message":"Load failed","causeName":"Error"}
Trong ví dụ với Error chuẩn không có trường enumerable bổ sung, stringify cho object rỗng. cause được tạo bởi constructor là thuộc tính không enumerable. Không suy ra rằng log đã giữ chuỗi nguyên nhân chỉ vì đã gọi JSON.stringify(error).
Record trên là ví dụ chọn ba trường, không phải serializer lỗi tổng quát hoặc mẫu response công khai. Với logger thực tế, kiểm tra cách nó xuất Error và cause, giới hạn độ sâu và xử lý vòng tham chiếu nếu dữ liệu tùy biến có thể tạo vòng. Message, stack và cause đều cần chính sách lọc trước khi gửi ra ngoài môi trường tin cậy.
5. Tách thông báo người dùng khỏi dữ liệu điều tra
Thông báo ở giao diện nên giúp người dùng quyết định bước tiếp theo. Chuỗi lỗi nội bộ phục vụ kỹ thuật có thể chứa tên file hoặc chi tiết của thư viện. Không tự động gửi toàn bộ object Error về client chỉ vì đã thêm cause.
Cause diễn tả một nguyên nhân được bọc bằng ngữ cảnh. Nếu có nhiều tác vụ độc lập cùng thất bại, cần mô hình nhiều lỗi thích hợp; đừng ghép tùy tiện tất cả lỗi thành một chuỗi cause giả như chúng gây ra nhau.
6. Kiểm thử cả ngữ cảnh và nguyên nhân
- Bọc lỗi giữ đúng object gốc, không chỉ sao chép message.
- Thông báo ngoài diễn đạt đúng thao tác thất bại.
- JSON hợp lệ được trả về, JSON sai cú pháp tạo cause là SyntaxError.
- Dữ liệu sai kiểu bị phát hiện trước bước parse.
- Logger thực tế không âm thầm bỏ các trường cần điều tra.
- Cause không phải Error hoặc không tồn tại được xử lý có chủ đích.
Các đoạn code đã chạy bằng Node.js local, gồm kiểm tra identity, parse và kết quả JSON. Chưa kiểm thử logger hoặc giao diện ứng dụng thật. Tài liệu đối chiếu: Error.cause và Error.
Thêm ngữ cảnh ở đúng ranh giới và giữ nguyên nguyên nhân giúp lỗi dễ điều tra hơn. Giá trị của cause nằm ở liên kết thông tin, không phải ở số tầng Error được tạo ra.




Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.