JavaScript错误捕获和处理

240 阅读4分钟

start

2025年,回首过往,思绪如窗前的苍蝇,嗡嗡作响。此刻,我打开记忆的窗,倒一倒脑子,看看那些岁月里留下了什么。

try...catch...finally 局部错误处理

  • try...catch...finally 是最基本的错误捕获机制,用于捕获同步代码中的异常。
  • 语法:
try {
    // 可能会抛出错误的代码
} catch (error) {
    // 捕获到错误后的处理逻辑
    console.error("捕获到错误:", error.message);
} finally {
    // 无论是否捕获到错误,都会执行的代码
}
  • 示例:
try {
	throw new Error("这是一个主动触发的错误!");
} catch (error) {
	const { name, message, stack } = error;
	const errorInfo = {
		name, // 错误名称
		message, // 错误消息
		stack // 错误堆栈 协议/路径:行号:列号
	};
	console.dir(errorInfo);
} finally {
	console.log("执行完毕");
}
  • 注意事项:
    • try 块中的代码必须是可能会抛出错误的代码。
    • catch 块会捕获到错误对象,通常包含 message、stack 等属性。
    • finally 块是可选的,会在 try 块和 catch 块执行完毕后执行,无论是否捕获到错误,都会执行。

Promise 的局部错误处理

  • 在异步编程中,Promise 是常用的工具,它的错误处理方式与同步代码有所不同。

Promise 中的错误处理

  • .then() 中捕获错误
  • .catch() 中捕获错误
fetch("http://xxx").then((res) => {
	if (!res.ok) {
		throw new Error("网络请求失败");
	}
	return res.json();
}).then((data) => {
	console.log("返回数据:", data);
}).catch((error) => {
	console.error("捕获到错误:", error.message);
});
  • 注意事项:
    • 如果在 Promise 链中没有捕获错误,可能会导致未处理的拒绝(unhandled rejection)。
    • 可以在 Promise 链的最后添加 .catch() 来捕获所有未处理的错误。

async/await 的局部错误处理

  • async/await 是现代 JavaScript 中处理异步代码的更优雅方式,它允许你使用同步代码的风格来处理异步逻辑。
async function fetchData() {
	try {
		const res = await fetch("http://xxx");
		if (!res.ok) {
			throw new Error("网络请求失败");
		}
		const data = await res.json();
		console.log("返回数据:", data);
	} catch (error) {
		console.error("捕获到错误:", error.message);
	}
}
  • 注意事项:
    • await 必须在 async 函数中使用。
    • async/await 的错误处理方式与 try...catch 一致,非常适合处理异步代码中的错误。

全局错误捕获

  • 除了局部捕获错误外,还可以通过全局错误捕获机制来处理未被捕获的错误。

window.onerror

  • window.onerror 是一个全局错误处理程序,用于捕获未被 try...catch 捕获的同步错误。
window.onerror = function(message, source, lineno, colno, error) {
	console.error("捕获到错误:", message, source, lineno, colno, error); // 可以将错误信息发送到服务器
	// 返回 true 表示错误已被处理,浏览器不会显示默认的错误提示
	return true;
}
  • 参数:
    • 错误消息(message):描述错误的字符串。
    • 文件名(source):发生错误的脚本文件的路径。
    • 行号(lineno):发生错误的代码行号。
    • 列号(colno):发生错误的代码列号。
    • 错误对象(error):一个 Error 对象,包含更多关于错误的信息。
  • 测试代码:throw new Error("这是一个主动触发的错误!");
  • 注意事项:
    • 全局性:window.onerror 是全局的错误处理器,它会捕获所有未被 try...catch 捕获的错误。
    • 返回值:如果返回 true,表示错误已被处理,浏览器不会显示默认的错误提示;如果不返回或返回 false,浏览器可能会显示默认的错误提示。
    • 兼容性:window.onerror 在大多数现代浏览器中都得到了支持,但在某些旧版本浏览器中可能行为略有不同。
    • 限制:它无法捕获异步错误(如 setTimeout 或 Promise 中的错误)。对于这些情况,可以使用 Promise.prototype.catch 或 process.on('unhandledRejection')(在 Node.js 中)来捕获。

window.onunhandledrejection

  • window.onunhandledrejection 用于捕获未被 Promise.catch 捕获的异步错误。
window.onunhandledrejection = function(e) {
	// 可以将错误信息发送到服务器
	const data = {
		id: e.reason && e.reason.id,
		message: e.reason && e.reason.message,
		href: window.location.href,
	};
	console.log('Promise 错误捕捉', data)
};
  • 测试代码:
Promise.reject({
	id: 8,
	message: '我是消息'
});
  • 注意事项:
    • 默认行为:默认情况下,浏览器会在控制台中打印未处理的 Promise 拒绝错误信息,但不会阻止程序的执行。
    • 阻止默认行为:如果在事件处理器中调用了 event.preventDefault(),可以阻止浏览器的默认行为(例如控制台打印错误信息)。

总结

  • 明确错误处理逻辑:在代码中明确哪些地方可能会抛出错误,并合理使用 try...catch 或 .catch()。
  • 统一错误处理:通过全局错误捕获机制(window.onerror 和 window.onunhandledrejection)统一处理未被捕获的错误。
  • 记录错误日志:将捕获到的错误信息上报到服务器,方便后续分析和修复。
  • 用户体验友好:在捕获到错误时,向用户展示友好的提示信息,而不是直接显示错误堆栈。
  • 避免过度捕获:不要在不必要的地方捕获错误,以免掩盖潜在问题。

end

恳请诸位同仁、挚友、兄弟姐妹不吝赐教,多多指点!