前端错误的分类
系统异常
网络异常
XMLHttpRequest
请求异常Fetch
请求异常-
应用异常
Error:错误的基类,其他错误都继承自该类型。
- EvalError : 与
eval()
有关的错误。 - RangeError : 表示这个值不在允许值集或范围内。
- ReferenceError : 表示发现一个无效的引用。
- SyntaxError : 表示发生了解析错误。
- TypeError :当其它类型错误都不符合时,TypeError 用于指示一个不成功的操作。
- URIError :表示用于处理 URI 的函数(encodeURI 或 decodeURl)使用方式与其定义的不兼容。
- 异常参考:Top 10 JavaScript errors from 1000+ projects
异常捕获
try/catch/finally
```javascript try { var a = 1; var b = a + c; } catch (error) { // 捕获处理 console.log(error); // ReferenceError: c is not defined logger.error(“catch”, error); } finally { throw new Error(“error”); }
**思考: 如果 catch 块和 finally 块都抛出异常,catch 块的异常是否能抛出?**<br />当该 `finally` 块引发异常时,它将有效地隐藏从该块引发的异常,并将 `catch` 最终引发该异常。因此,重要的是要么在捕获时记录异常,要么确保 `finally` 块本身不会引发异常。
<a name="TFptk"></a>
## window.onerror
> 请注意 `window.error` 无法捕获静态资源异常和 JS 代码错误。
```javascript
/**
* @param {String} message 错误信息
* @param {String} source 错误文件路径
* @param {Number} lineno 错误行号
* @param {Number} colno 错误列号
* @param {Object} error Error对象(对象)
*/
window.onerror = function (message, source, lineno, colno, error) {
console.log(`捕获到异常:${ message, source, lineno, colno, error }`);
logger.error("oneror", JSON.stringify({ message, source, lineno, colno, error }));
};
静态资源加载 异常
<script>
function errorHandler(error) {
console.log(`捕获到静态资源加载异常: ${error}`);
logger.error("onerror", JSON.stringify(error));
}
</script>
<script src="http://cdn.xxx.com/js/test.js" onerror="errorHandler(this)"></script>
<link rel="stylesheet" href="http://cdn.xxx.com/styles/index.css" onerror="errorHandler(this)">
Promise 异常
window.addEventListener("unhandledrejection", event => {
console.warn(`UNHANDLED PROMISE REJECTION: ${event.reason}`);
logger.error("promise", JSON.stringify(event));
event.preventDefault();
});
// 或
window.onunhandledrejection = event => {
console.warn(`UNHANDLED PROMISE REJECTION: ${event.reason}`);
logger.error("promise", JSON.stringify(event));
event.preventDefault();
};
Vue
/**
* @name Vue 异常上报
* @param {{message,name,script,line,column,stack}} err error 对象
* @param {String} vm 抛出异常的 Vue 实例对象
* @param {String} info Vue 特定的错误信息,比如错误所在的生命周期钩子
*/
Vue.config.errorHandler = (err, vm, info) => {
console.log("vue errorHandler", { err, vm, info });
logger.error("vue error", JSON.stringify({ err, vm, info }));
};
React
import React from 'react'
import { Modal } from 'antd'
import './styles.scss'
export default class ErrorBoundary extends React.Component {
state = { hasError: false, error: null, tipText: null }
componentDidCatch(error, info) {
console.error(error, info)
logger.error('react error', JSON.stringify({ error, info }))
if (error && (error.toString().indexOf('ChunkLoadError') === 0 || error.toString().indexOf('Error: Loading CSS ') === 0)) {
// 监测到Webpack异步模块加载失败
Modal.confirm({
title: '检测到网站可能有更新,需要刷新页面',
okText: '刷新',
cancelText: '关闭',
maskClosable: false,
onOk: () => {
location.reload()
},
})
this.setState({ hasError: true, tipText: '网站可能有更新,请刷新页面' })
} else {
this.setState({ hasError: true, error, tipText: null })
}
}
render() {
if (this.state.tipText) {
return (
<div className="page-error page-standard">
<h2 className="title">{this.state.tipText}</h2>
</div>
)
} else if (this.state.hasError) {
return (
<div className="page-error page-standard">
<h2 className="title">抱歉,页面出错</h2>
<h5 className="tip">请尝试刷新页面,或联系技术人员,以下是错误信息:</h5>
<div className="error-message">{this.state.error ? this.state.error.toString() : '错误:未知错误'}</div>
</div>
)
}
return this.props.children
}
}
// 使用案例:启动入口页面包裹
import React from 'react'
import { render } from 'react-dom'
import ErrorBoundary from 'components/ErrorBoundary'
const appRoot = document.getElementById('root')
appRoot.setAttribute('notranslate', true)
render(<ErrorBoundary>{/* code... */}</ErrorBoundary>, appRoot)
延伸: 跨域的 js 运行错误可以捕获吗,错误提示什么,应该怎么处理?
跨域之后 window.onerror
是无法捕获异常信息的,所以统一返回 Script error
,解决方案
- 在 script 标签增加 crossorigin=”anonymous” 属性
- 设置 Access-Control-Allow-Origin: *
监控平台搭建
这个应该每个公司都有自己的监控平台,这里不列举过多。
如果数据量过大,架构需要对行为记录存储的设计与成本进行考虑。如容器存储与存放时间等
数据监控
- PV:即页面浏览量或点击量
- UV:指访问某个站点或点击某条新闻的不同IP地址的人数
- 页面停留时长
- 用户与数据来源
-
性能监控
不同环境下机型与系统下的首屏加载时间
- DNS、TCP、request、页面渲染、load、加载、白屏等耗时时间
异常监控
JavaScript与样式异常埋点
数据上报可以在延伸扩展:即时,批量,主动等上报方式,可根据业务优先级来决定
代码埋点与数据上报