关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

如何搭建前端异常监控系统 #102

发布时间:2023-06-27 18:00:39
什么是异常 是指用户在使用应用时,无法得到预期的结果。不同的异常带来的后果程度不同,轻则引起用户使用不悦,重则导致产品无法使用,从而使用户丧失对产品的认可。 为什么要处理异常 增强用户体验 远程定位问题 无法复现问题,特别是移动端,各种原因,可能是系统版本,机型等等 前端有哪些异常 异常 频率 JavaScript 异常(语法错误、代码错误) 经常 静态资源加载异常(img、js、css) 偶尔 Ajax 请求异常 偶尔 承诺异常 较少 iframe 异常 较少 如何捕获异常 尝试捕获 try-catch只能捕获同步运行错误,对语法和异步错误却捕获不到。 1、同步运行错误 try { kill; } catch(err) { console.error('try: ', err); } 结果:try: ReferenceError: kill is not defined 2、无法捕获语法错误 try { let name = '1; } catch(err) { console.error('try: ', err); } 结果:Unterminated string constant 编译器能够阻止运行语法错误。 3、无法捕获异步错误 try { setTimeout(() => { undefined.map(v => v); }, 1000); } catch(err) { console.error('try: ', err); } 结果:Uncaught TypeError: Cannot read property 'map' of undefined 窗口错误 当 运行时错误(包括语法错误)发生时, 会触发一个 接口的 事件,并执行 若该函数返回 ,则阻止执行默认事件处理函数。JavaScriptwindowErrorEventerrorwindow.onerror()true 1、同步运行错误 /** * @param {String} message 错误信息 * @param {String} source 出错文件 * @param {Number} lineno 行号 * @param {Number} colno 列号 * @param {Object} error error对象 */ window.onerror = (message, source, lineno, colno, error) => { console.error('捕获异常:', message, source, lineno, colno, error); return true; }; kill; 结果:捕获异常: Uncaught ReferenceError: kill is not defined 2、无法捕获语法错误 /** * @param {String} message 错误信息 * @param {String} source 出错文件 * @param {Number} lineno 行号 * @param {Number} colno 列号 * @param {Object} error error对象 */ window.onerror = (message, source, lineno, colno, error) => { console.error('捕获异常:', message, source, lineno, colno, error); return true; }; let name = '1; 结果:Unterminated string constant 编译器能够阻止运行语法错误。 3、异步错误 /** * @param {String} message 错误信息 * @param {String} source 出错文件 * @param {Number} lineno 行号 * @param {Number} colno 列号 * @param {Object} error error对象 */ window.onerror = (message, source, lineno, colno, error) => { console.error('捕获异常:', message, source, lineno, colno, error); return true; }; setTimeout(() => { undefined.map(v => v); }, 1000); 结果:捕获异常: Uncaught TypeError: Cannot read property 'map' of undefined` window.addEventListener('error') 当一项资源(如 或 )加载失败,加载资源的元素会触发一个 接口的 事件,并执行该元素上的 处理函数。这些 事件不会向上冒泡到 ,不过(至少在 Firefox 中)能被单一的 . 捕获。 结果:捕获异常:Event {isTrusted: true, type: "error", target: img, currentTarget: Window, eventPhase: 1, …} window.addEventListener('unhandledrejection') 当 被 且没有 处理器的时候,会触发 事件;这可能发生在 下,但也可能发生在 中。 这对于调试回退错误处理非常有用。PromiserejectrejectunhandledrejectionwindowWorker window.addEventListener("unhandledrejection", (err) => { err.preventDefault(); console.error('捕获异常:', err); }); Promise.reject('promise'); 结果:捕获异常:PromiseRejectionEvent {isTrusted: true, promise: Promise, reason: "promise", type: "unhandledrejection", target: Window, …} Vue Vue.config.errorHandler = (err, vm, info) => { console.error('捕获异常:', err, vm, info); } React React16,提供了一个内置函数 ,使用它可以非常简单的获取到 下的错误信息。componentDidCatchReact componentDidCatch(error, info) { console.error('捕获异常:', error, info); } 但是,推荐ErrorBoundary 用户界面中的 错误不应破坏整个应用程序。为了为 用户解决此问题, 引入了“错误边界”的新概念。JavaScriptReactReact16 新建 组件:ErrorBoundary.jsx import React from 'react'; import { Result, Button } from 'antd'; class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false, info: '' }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, info) { this.setState({ info: error + '' }); } render() { if (this.state.hasError) { // 你可以渲染任何自定义的降级 UI return ( Report feedback} /> ); } return this.props.children; } } export default ErrorBoundary; 使用: 注意 错误边界不会捕获以下方面的错误: 事件处理程序 异步代码(例如 或 回调)setTimeoutrequestAnimationFrame 服务器端渲染 在错误边界本身(而不是其子级)中引发的错误 iframe 由于浏览器设置的“同源策略”,无法非常优雅的处理 异常,除了基本属性(例如其宽度和高度)之外,无法从 获得很多信息。iframeiframe