try
Vùng code có thể phát sinh lỗi
Exception Handling là cơ chế quản lý các tình huống bất thường khi chạy chương trình — những tình huống khiến luồng thực thi bình thường không thể tiếp tục an toàn. Khi lỗi được ném (throw), JavaScript sẽ ngắt luồng hiện tại và “unwind” call stack cho đến khi gặp catch; nếu không có, chương trình kết thúc trong trạng thái lỗi.
throw chủ động ném lỗi để dừng luồng bình thường và chuyển sang cơ chế bắt lỗi.
throw expression;function parseAge(x) { const n = Number(x); if (!Number.isInteger(n) || n < 0) { throw new RangeError("Age must be a non-negative integer"); } return n;}
parseAge(-5); // RangeError: Age must be a non-negative integerparseAge("abc"); // RangeError: Age must be a non-negative integer// ❌ Hoạt động nhưng không có stack tracethrow "Something went wrong";
// ✅ Luôn dùng Error objectthrow new Error("Something went wrong");throw trong async function làm Promise reject:
async function loadData() { throw new Error("Failed to load"); // tương đương: return Promise.reject(new Error("Failed to load"))}
loadData().catch(e => console.error(e.message));try
Vùng code có thể phát sinh lỗi
catch
Bắt và xử lý lỗi nếu try ném ra
finally
Luôn chạy sau cùng — dù có lỗi, return, hay break
try { // code có thể gây lỗi} catch (error) { // xử lý lỗi} finally { // dọn dẹp — luôn chạy}try { const data = JSON.parse('{"x":1}'); console.log(data.x); // 1} catch (e) { console.error("JSON invalid:", e.message);} finally { console.log("Xong"); // luôn chạy}async function fetchJson(url) { try { const res = await fetch(url); if (!res.ok) throw new Error(`HTTP ${res.status}`); return await res.json(); } catch (e) { console.error("Fetch failed:", e.message); throw e; // rethrow để caller biết } finally { // dọn dẹp (tắt loading, v.v.) }}Bắt lỗi theo kiểu cụ thể:
try { riskyOperation();} catch (e) { if (e instanceof TypeError) { console.error("Type error:", e.message); } else if (e instanceof RangeError) { console.error("Range error:", e.message); } else { throw e; // không biết → ném tiếp }}finally| Loại | Khi nào xảy ra |
|---|---|
Error | Lỗi chung |
TypeError | Sai kiểu dữ liệu (null.foo, gọi non-function) |
RangeError | Giá trị ngoài phạm vi (new Array(-1)) |
ReferenceError | Biến chưa khai báo |
SyntaxError | Cú pháp sai (thường lúc parse) |
URIError | decodeURI('%') — URI không hợp lệ |
try { undeclaredVar;} catch (e) { console.log(e.name); // "ReferenceError" console.log(e.message); // "undeclaredVar is not defined" console.log(e.stack); // full stack trace}class AuthError extends Error { constructor(message, cause) { super(message, { cause }); // Error.cause (ES2022) this.name = "AuthError"; this.code = "AUTH_FAILED"; }}
function authenticate(token) { if (!token) throw new AuthError("Token missing"); // ...}try { authenticate(null);} catch (e) { if (e instanceof AuthError) { console.log(e.code); // "AUTH_FAILED" console.log(e.message); // "Token missing" }}Thêm ngữ cảnh vào lỗi gốc mà không mất thông tin:
try { await saveToDB(item);} catch (e) { throw new Error("Failed to save order", { cause: e }); // caller có thể truy cập: error.cause → lỗi gốc}Luôn throw Error object
Không throw string/number — cần name, message, stack để debug
Không nuốt lỗi
Log rồi rethrow nếu không thể xử lý triệt để ở tầng hiện tại
Throw đúng loại
Tham số sai → TypeError/RangeError; auth sai → custom AuthError
Bọc lỗi (wrapping)
Dùng { cause } để thêm ngữ cảnh khi ném lại lỗi
| Cấu trúc | Mô tả | Ghi nhớ |
|---|---|---|
throw | Ném lỗi, dừng luồng | Luôn throw Error object |
try | Vùng có thể lỗi | Đặt code “nguy hiểm” ở đây |
catch(e) | Bắt và xử lý lỗi | Check instanceof nếu cần |
finally | Luôn chạy sau cùng | Dọn dẹp — đừng return ở đây |
Error.cause | Chuỗi lỗi (ES2022) | Giữ nguyên lỗi gốc qua nhiều tầng |