JavaScript 异常捕获全攻略:从同步到异步,优雅处理运行时错误

2025-12-11

不用担心,我会用友好、清晰的简体中文来解释,并提供常见的陷阱和替代方案的示例代码。

try...catch 语句用于测试代码块中的错误,并在发生错误时优雅地处理它,防止整个程序崩溃。

基本的结构如下

try {

// 尝试执行的代码块

// 如果这里出现错误(异常),执行会立即停止,并跳转到 catch 块

} catch (error) {

// 捕获到错误时执行的代码块

// error 参数包含有关发生错误的详细信息

console.error("捕获到一个错误:", error.message);

} finally {

// (可选) 无论 try 块是否发生错误,finally 块中的代码总是会被执行

// 常用语清理资源或关闭连接

console.log("try...catch 执行结束。");

}

即使是经验丰富的开发者,在使用 try...catch 时也可能会遇到一些小问题。

try...catch 不能直接捕获在它同步执行后才发生的异步代码中的错误,例如在 setTimeout 回调函数中发生的错误。

错误示例 (无法捕获)

try {

setTimeout(() => {

// 这个错误发生在 try...catch 块已经执行完毕之后

// try...catch 无法捕获它

throw new Error("这是一个异步错误!");

}, 100);

} catch (error) {

// 这个 catch 块不会被执行!

console.error("捕获到:", error.message);

}

// 输出: (程序可能会崩溃,或者错误会被全局捕获)

解决方案将 try...catch 放在异步操作内部

你需要将 try...catch 移动到异步回调函数内部,以确保错误在它发生的地方被捕获。

setTimeout(() => {

try {

// 错误现在在它发生的回调函数内部被捕获

throw new Error("这是一个异步错误!");

} catch (error) {

console.error(" 成功捕获异步错误:", error.message);

}

}, 100);

// 输出: 成功捕获异步错误: 这是一个异步错误!

对于 Promise,你应该使用 .catch() 方法来处理错误,而不是外部的同步 try...catch。

错误示例 (无法捕获 Promise 错误)

const myPromise = new Promise((resolve, reject) => {

// Promise 内部的错误不会被外部的 try...catch 捕获

reject("Promise 被拒绝!");

});

try {

myPromise.then(result => {

console.log(result);

});

} catch (error) {

// 不会被执行!

console.error("捕获到 Promise 错误:", error);

}

解决方案使用 .catch()

const myPromise = new Promise((resolve, reject) => {

reject("Promise 被拒绝!");

});

myPromise

.then(result => {

console.log(result);

})

.catch(error => {

// 这是处理 Promise 拒绝的推荐方式

console.error(" 成功捕获 Promise 错误:", error);

});

// 输出: 成功捕获 Promise 错误: Promise 被拒绝!

在现代 JavaScript 中,尤其是涉及到异步操作时,有一些更优雅、更强大的错误处理方法。

当你使用 async/await 来处理 Promise 时,try...catch 就能像同步代码一样工作,这是处理异步错误的最佳实践!

示例代码

function fetchData() {

return new Promise((resolve, reject) => {

// 模拟一个网络请求失败

setTimeout(() => reject(new Error("网络请求失败,状态码 500")), 500);

});

}

async function handleData() {

try {

// await 会等待 Promise 完成,如果 Promise 被 reject,它会抛出一个错误

const data = await fetchData();

console.log("获取到的数据:", data);

} catch (error) {

// 外部的 try...catch 成功捕获了 Promise 的 reject

console.error(" 在 async/await 中捕获到错误:", error.message);

}

}

handleData();

// 输出: 在 async/await 中捕获到错误: 网络请求失败,状态码 500

对于那些你没有预料到或没有在局部捕获的错误,你可以设置全局的错误处理机制。

// 捕获未被 try...catch 捕获的同步运行时错误

window.onerror = function(message, source, lineno, colno, error) {

console.error("全局捕获到同步错误:", message);

return true; // 返回 true 阻止默认的浏览器错误处理

};

// 捕获未被 .catch() 捕获的 Promise 拒绝

window.addEventListener('unhandledrejection', function(event) {

console.error('全局捕获到未处理的 Promise 拒绝:', event.reason);

// event.preventDefault(); // 可以用来阻止控制台显示默认错误

});

// 测试一个未捕获的 Promise 拒绝

new Promise((_, reject) => reject('我没有 .catch()!'));

process.on('uncaughtException', (error) => {

// 捕获未被 try...catch 捕获的同步错误

console.error('全局捕获到未处理的同步异常:', error.message);

// 注意: 在 Node.js 中,未捕获的异常后进程处于不确定状态,通常建议安全退出

// process.exit(1);

});

场景推荐的错误处理方法同步代码try...catch异步回调函数 (setTimeout, event listeners)在回调函数内部使用 try...catchPromise 链使用 .then().catch()使用 async/await在 async 函数内部使用 try...catch (最佳实践)全局未捕获的错误window.onerror / window.unhandledrejection (浏览器) 或 process.on('uncaughtException') (Node.js)希望这个详细的解释能帮助你更好地理解和使用 JavaScript 中的 try...catch 及其替代方案!