JavaScript中的错误类型。
// Error: 基础错误类型
throw new Error("通用错误");
// SyntaxError: 语法错误
// throw new SyntaxError("语法错误");
// ReferenceError: 引用错误
// throw new ReferenceError("变量未定义");
// TypeError: 类型错误
throw new TypeError("类型错误");
// RangeError: 范围错误
throw new RangeError("超出范围");
// URIError: URI错误
throw new URIError("URI编码错误");
// EvalError: eval错误(已废弃)
// 自定义错误类
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = "ValidationError";
this.field = field;
}
}
class NetworkError extends Error {
constructor(message, statusCode) {
super(message);
this.name = "NetworkError";
this.statusCode = statusCode;
}
}
// 使用
function validateUser(user) {
if (!user.name) {
throw new ValidationError("名称不能为空", "name");
}
if (!user.email) {
throw new ValidationError("邮箱不能为空", "email");
}
}
抛出错误。
// 抛出错误
throw new Error("出错了");
// 抛出任意值
throw "错误字符串";
throw { message: "错误对象" };
throw 123;
// 推荐使用Error对象
throw new Error("错误信息");
function divide(a, b) {
if (b === 0) {
throw new Error("除数不能为0");
}
return a / b;
}
function getAge(age) {
if (typeof age !== "number") {
throw new TypeError("年龄必须是数字");
}
if (age < 0 || age > 150) {
throw new RangeError("年龄必须在0-150之间");
}
return age;
}
捕获和处理错误。
try {
// 可能出错的代码
const result = JSON.parse('{"name": "东巴文"');
} catch (error) {
// 处理错误
console.error(error.name); // SyntaxError
console.error(error.message); // 错误信息
console.error(error.stack); // 错误堆栈
}
try {
// 可能出错的代码
const data = fetchData();
processData(data);
} catch (error) {
console.error(error);
} finally {
// 无论是否出错都执行
cleanup();
}
// 实际应用
let connection;
try {
connection = openConnection();
const data = connection.read();
return processData(data);
} catch (error) {
logError(error);
throw error;
} finally {
if (connection) {
connection.close();
}
}
try {
try {
throw new Error("内部错误");
} catch (innerError) {
console.log("捕获内部错误:", innerError.message);
throw new Error("外部错误");
}
} catch (outerError) {
console.log("捕获外部错误:", outerError.message);
}
错误的传播机制。
function a() {
throw new Error("a中的错误");
}
function b() {
a();
}
function c() {
b();
}
try {
c();
} catch (error) {
console.log(error.message); // "a中的错误"
}
// 回调中的错误
function asyncOperation(callback) {
setTimeout(() => {
try {
const result = riskyOperation();
callback(null, result);
} catch (error) {
callback(error);
}
}, 1000);
}
// Promise中的错误
async function fetchUser() {
try {
const response = await fetch("/api/user");
return response.json();
} catch (error) {
console.error("获取用户失败:", error);
throw error;
}
}
// 事件处理中的错误
process.on("uncaughtException", (error) => {
console.error("未捕获的异常:", error);
});
process.on("unhandledRejection", (reason, promise) => {
console.error("未处理的Promise拒绝:", reason);
});
常见的错误处理模式。
// 返回 { error, data } 模式
function divide(a, b) {
if (b === 0) {
return { error: new Error("除数不能为0"), data: null };
}
return { error: null, data: a / b };
}
const { error, data } = divide(10, 0);
if (error) {
console.error(error);
} else {
console.log(data);
}
// Result类型模式
class Result {
static ok(value) {
return { ok: true, value };
}
static err(error) {
return { ok: false, error };
}
}
function divide(a, b) {
if (b === 0) {
return Result.err("除数不能为0");
}
return Result.ok(a / b);
}
const result = divide(10, 2);
if (result.ok) {
console.log(result.value);
} else {
console.error(result.error);
}
// 错误边界组件(React风格)
class ErrorBoundary {
constructor() {
this.hasError = false;
this.error = null;
}
try(fn) {
try {
const result = fn();
return result;
} catch (error) {
this.hasError = true;
this.error = error;
this.onError(error);
return null;
}
}
onError(error) {
console.error("错误边界捕获:", error);
}
reset() {
this.hasError = false;
this.error = null;
}
}
// 使用
const boundary = new ErrorBoundary();
boundary.try(() => {
throw new Error("测试错误");
});
处理未捕获的错误。
// 全局错误处理
window.onerror = function(message, source, lineno, colno, error) {
console.error("全局错误:", message);
console.error("文件:", source);
console.error("行号:", lineno);
return true; // 阻止默认行为
};
// Promise未处理拒绝
window.addEventListener("unhandledrejection", function(event) {
console.error("未处理的Promise拒绝:", event.reason);
event.preventDefault();
});
// 资源加载错误
window.addEventListener("error", function(event) {
if (event.target !== window) {
console.error("资源加载失败:", event.target.src);
}
}, true);
// 未捕获异常
process.on("uncaughtException", (error) => {
console.error("未捕获的异常:", error);
// process.exit(1);
});
// 未处理的Promise拒绝
process.on("unhandledRejection", (reason, promise) => {
console.error("未处理的Promise拒绝:", reason);
});
// 警告
process.on("warning", (warning) => {
console.warn("警告:", warning);
});
记录和管理错误。
class ErrorLogger {
constructor() {
this.errors = [];
}
log(error, context = {}) {
const entry = {
timestamp: new Date().toISOString(),
name: error.name,
message: error.message,
stack: error.stack,
context,
url: window.location.href,
userAgent: navigator.userAgent
};
this.errors.push(entry);
this.sendToServer(entry);
return entry;
}
sendToServer(entry) {
fetch("/api/logs/error", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(entry)
}).catch(console.error);
}
getErrors() {
return this.errors;
}
clear() {
this.errors = [];
}
}
const logger = new ErrorLogger();
// 使用
try {
riskyOperation();
} catch (error) {
logger.log(error, { operation: "riskyOperation" });
}
掌握了错误处理后,让我们继续学习:
东巴文(db-w.cn) - 让编程学习更简单
🎯 东巴文寄语:良好的错误处理是健壮应用的基础,理解错误类型、正确使用try-catch、实现全局错误处理是每个开发者的必备技能。在 db-w.cn,我们帮你构建可靠的JavaScript应用!