引言
简介
异常处理在前端开发中的重要性不言而喻。构建稳定、可靠的前端应用,防止用户面临不友好的错误信息或者导致应用崩溃,使开发人员更容易追踪和调试问题。
目的
前端异常处理应当在代码中使用 try-catch 块或其他适当的方式捕获异常,记录异常的详细信息,以便及时发现问题并更好地诊断和修复问题;在关键业务逻辑中引入容错机制,确保系统在面临异常情况时依然能够提供基本的功能;建立异常监控系统,及时发现并通知开发团队异常情况,以便快速响应和修复;
前端异常处理
1、异常主动上报场景
为保证代码统一性,vue文件里处理的逻辑捕获均使用 try-Catch 形式,异步代码用 async-await 形式:
a、异步代码中的错误处理:
try {
// 异步操作,如AJAX请求或定时器
const response = await axios(url, options);
} catch (error) {
// console.error("发生错误:", error);
errorHandler(error);
}
b、JSON 解析:
try {
var jsonData = JSON.parse(invalidJsonString);
} catch (error) {
// console.error("JSON解析错误:", error);
errorHandler(error);
}
c、DOM 操作:
try {
// 可能会引发DOM异常的操作
} catch (error) {
// console.error("DOM操作错误:", error);
errorHandler(error);
}
d、资源加载:
try {
// 尝试加载资源,如图片、脚本等
} catch (error) {
// console.error("资源加载错误:", error);
errorHandler(error);
}
e、本地存储:
try {
// 尝试访问本地存储
} catch (error) {
// console.error("本地存储访问错误:", error);
errorHandler(error);
}
f、参数为函数,被调用时:
function test(fn){
try {
fn()
} catch (error) {
errorHandler(error);
}
}
在这些情况下,try-catch 语句可以帮助捕获异常并提供更友好的错误处理,避免整个应用程序崩溃。
2、统一的错误处理规范
- 编写一个统一的错误处理函数,接收错误对象,并执行适当的操作,如打印错误对象、向服务器上报错误、显示用户友好的错误消息等,可以帮助简化代码并确保一致性。
function errorHandler(error, msg) {
// 打印错误对象
console.error('Error:', error);
// 向服务器主动报告错误
reportErrorToServer(error);
// 还可以执行其他适当的操作,如在非生产环境显示通知
if(!prd) showErrorMessageToUser(msg || '系统异常,请稍后再试');
}
// 例子:在代码中调用错误处理函数
try {
throw new Error('This is a test error.');
} catch (error) {
errorHandler(error);
}
3、异常日志规范
在JavaScript应用程序中,实现异常日志规范有助于快速诊断和解决问题。通常包括以下关键信息:
a、错误消息: 记录详细的错误消息,包括错误描述、发生的位置以及可能的原因。这可以通过捕获错误对象的message属性和堆栈信息来实现。
b、堆栈跟踪: 记录堆栈跟踪信息,以便追踪异常发生的位置。这有助于开发人员迅速定位和修复问题。
c、用户上下文: 如果可能,记录与用户相关的上下文信息,例如用户ID、操作、浏览器信息等。这有助于理解用户遇到的问题背后的背景。
d、时间戳: 记录异常发生的时间戳,以便能够按时间顺序检查日志,追溯问题发生的时间。
e、环境信息: 记录应用程序运行的环境信息,包括浏览器版本、操作系统、设备信息等。这对于排查特定环境下的问题很有帮助。
f、保护用户隐私: 在记录日志时,确保不包含敏感信息,以保护用户隐私。
g、存储与管理:描述日志的存储方式和周期,以及如何安全高效地管理这些日志。
4、异常编码规范
在代码中使用try-catch块或其他适当的方式捕获异常,以便及时发现问题。
- 同步代码的错误处理
try {
const errorCake = dessert.getDessert(CAKE);
} catch(error) {
errorHandler(error);
}
- 异步代码setTimeout和addEventListener的错误处理
button.addEventListener("click", function() {
try {
throw Error("error");
} catch(error) {
errorHandler(error);
}
});
- 异步代码Promise的错误处理
function fetchData(url, options) {
return new Promise((resolve, reject) => {
// 异步请求
fetch(url, options)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then(data => {
resolve(data);
})
.catch(error => {
errorHandler(error, '页面接口出错,请稍后再试');
reject(error);
});
});
}
- async/await的错误抛出
async function fetchData(url, options) {
try {
const response = await axios(url, options);
if (response.status !== 200) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.data;
} catch (error) {
errorHandler(error, '页面接口出错,请稍后再试');
}
}
5、异常错误捕获方式
在 JavaScript 开发中,正确处理执行异常错误是提高应用稳定性和用户体验的关键一环。JavaScript 提供了多种方式来捕获和处理执行时异常,包括同步和异步错误。
-
try...catch语句
只能捕获同步代码中的错误。在异步代码中,如 setTimeout 或 Promise 内部抛出的错误,try...catch 无法直接捕获。
try {
// 尝试执行的代码,可能会抛出异常 throw new Error('Oops!');
} catch (error) {
// 错误处理逻辑 console.log(error.message);
}
-
window.onerror
可以捕获未被 try...catch 捕获的所有同步和一部分异步错误。可以捕获资源(如图片、脚本、样式表等)加载失败的错误。只能捕获发生在同源脚本中的错误。不适合处理异步错误,如通过 fetch 发起的网络请求错误等。
window.onerror = function(message, source, lineno, colno, error) {
console.log('捕获到全局错误:', message);
return true; // 阻止默认处理(如浏览器控制台的错误报告)
};
-
window.addEventListener('error')
不会覆盖其他的 error 事件监听器,可以添加多个监听器。通过为特定的 HTML 元素(如 <img>、<script>、<link> 等)添加 error 事件监听器,可以更精细地处理单个资源的加载失败。
如果你需要全局捕获并处理所有类型的错误(包括语法错误、运行错误以及资源加载错误),window.onerror 是一个不错的选择。如果你需要对特定资源的加载错误进行详细监控和特定处理,应该使用 addEventListener 方法来监听这些资源的 error 事件。
window.addEventListener('error', function(event) {
console.log('捕获到错误:', event.message);
event.preventDefault(); // 阻止默认处理
});
-
Promise.catch或async/await中的try...catch
异步友好:可以在异步代码块中直接处理错误。
fetch('some-url')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.catch(error => {
console.log('有一个问题:', error.message);
});
-
addEventListener('unhandledrejection')
用来捕获Promise中未被处理的拒绝(即未被.catch()捕获或reject没有对应的catch处理器的情况)。
window.addEventListener('unhandledrejection', function(event) {
console.error('Promise 拒绝未被处理:', event.promise);
console.error('拒绝的原因:', event.reason);
// event.promise 是被拒绝的 Promise 对象
// event.reason 是 Promise 被拒绝的原因
});