前端监控系统之代码运行错误类型及相应的处理方式

常见JS执行错误

SyntaxError:语法错误,解析时发生语法错误

// 在控制台运行

// 一般语法错误
const xx,

// 特殊语法错误
JSON.parse('');

SyntaxError在构建阶段,甚至本地开发阶段就会被发现;
而特殊语法错误可以被所有错误捕获方式捕获。

TypeError:类型错误,值不是所期待的类型

// 控制台运行 
const person = undefined;
person.name;

ReferenceError:引用错误,引用未声明的变量

// 控制台运行 
nodefined;

RangeError:范围错误,当一个值不在其所允许的范围或者集合中

// 控制台运行
// 爆栈
(function fn() {
    fn();
})();

网络错误

ResourceError:资源加载错误

// 控制台运行 
new Image().src = '/remote/image/notdeinfed.png';

HttpError:http请求错误

// 控制台运行 
fetch('/remote/notdefined');

搜集错误

所有起因来源于错误,那我们如何进行错误捕获。

try/catch

能捕获常规运行时错误,语法错误和异步错误不行

// 常规运行时错误,可以捕获 ✅
try {
  console.log(notdefined);
} catch(e) {
  console.log('捕获到异常:', e);
}

// 语法错误,不能捕获 ❌
try {
  const notdefined,
} catch(e) {
  console.log('捕获到异常:', e);
}

// 异步错误,不能捕获 ❌
try {
  setTimeout(() => {
    console.log(notdefined);
  }, 0)
} catch(e) {
  console.log('捕获到异常:',e);
}

try/catch有它细致处理的优势,但缺点也比较明显。

window.onerror

当 JS 运行时错误发生时,window 会触发一个 ErrorEvent 接口的 error 事件。

/**
* @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});
}

先验证下几个错误是否可以捕获。​

window.onerror = function(message, source, lineno, colno, error) {
   console.log('捕获到异常:', {message, source, lineno, colno, error});
};
window.onload = function () {
  // 一般语法错误 ❌
  const xx,
  
  // 特殊语法错误 ✅
  JSON.parse('');

  // 类型错误 ✅
  const person = undefined;
  person.name;

  // 引用错误 ✅
  a;

  // 范围错误 ✅
  (function fn() {
    fn();
  })();

  // 资源加载错误 ❌
  new Image().src = 'aaa';

  // http请求错误 ❌
  fetch('aaa');

  // promise异步错误 ❌
  new Promise(() => {
    a;
  });

  // setTimeout/setInterval异步错误 ✅
  setTimeout(() => {
    b;
  }, 0);
};

window.onerror不能捕获语法错误和promise异步错误(包括网络错误、资源加载)。

window.addEventListener

当一项资源(如图片或脚本)加载失败,加载资源的元素会触发一个 Event 接口的 error 事件,这些 error 事件不会向上冒泡到 window,但能被捕获。而window.onerror不能监测捕获。

// 图片、script、css加载错误,都能被捕获 ✅
<script>
  window.addEventListener('error', (error) => {
     console.log('捕获到异常:', error);
  }, true)
</script>
<img src="https://yun.tuia.cn/image/kkk.png">
<script src="https://yun.tuia.cn/foundnull.js"></script>
<link href="https://yun.tuia.cn/foundnull.css" rel="stylesheet"/>
  
// new Image错误,不能捕获 ❌
<script>
  window.addEventListener('error', (error) => {
    console.log('捕获到异常:', error);
  }, true)
</script>
<script>
  new Image().src = 'https://yun.tuia.cn/image/lll.png'
</script>

// fetch错误,不能捕获 ❌
<script>
  window.addEventListener('error', (error) => {
    console.log('捕获到异常:', error);
  }, true)
</script>
<script>
  fetch('https://tuia.cn/test')
</script>

到目前为止,还有语法错误、promise异步错误、new Image资源加载错误还没有捕获方法。

语法错误可以在开发阶段依靠编辑器发现,上线的项目是不会出现语法错误的。

new Image运用的比较少,可以单独自己处理自己的错误,可以通过img.onerror = fn来单独处理。

但通用的fetch怎么办呢,fetch返回Promise,但Promise的错误不能被捕获,怎么办呢?​

Promise错误

1.普通Promise错误

try/catch不能捕获Promise中的错误

// try/catch 不能处理 JSON.parse 的错误,因为它在 Promise 中
try {
  new Promise((resolve,reject) => { 
    JSON.parse('')
    resolve();
  })
} catch(err) {
  console.error('in try catch', err)
}

// 需要使用catch方法
new Promise((resolve,reject) => { 
  JSON.parse('')
  resolve();
}).catch(err => {
  console.log('in catch fn', err)
})

2.async错误

try/catch不能捕获async包裹的错误

const getJSON = async () => {
  throw new Error('inner error')
}

// 通过try/catch处理
const makeRequest = async () => {
    try {
        // 捕获不到
        JSON.parse(getJSON());
    } catch (err) {
        console.log('outer', err);
    }
};

try {
    // try/catch不到
    makeRequest()
} catch(err) {
    console.error('in try catch', err)
}

try {
    // 需要await,才能捕获到
    await makeRequest()
} catch(err) {
    console.error('in try catch', err)
}

3.import chunk错误

import其实返回的也是一个promise,因此使用如下两种方式捕获错误

// Promise catch方法
import(/* webpackChunkName: "incentive" */'./index').then(module => {
    module.default()
}).catch((err) => {
    console.error('in catch fn', err)
})

// await 方法,try catch
try {
    const module = await import(/* webpackChunkName: "incentive" */'./index');
    module.default()
} catch(err) {
    console.error('in try catch', err)
}

小结:全局捕获Promise中的错误

以上三种其实归结为Promise类型错误,可以通过unhandledrejection捕获。
为了防止有漏掉的 Promise 异常,可通过unhandledrejection用来全局监听Uncaught Promise Error。

// 全局统一处理Promise
window.addEventListener("unhandledrejection", function(e){
  console.log('捕获到异常:', e);
});
fetch('https://tuia.cn/test')

Vue错误

由于Vue会捕获所有Vue单文件组件或者Vue.extend继承的代码,所以在Vue里面出现的错误,并不会直接被window.onerror捕获,而是会抛给Vue.config.errorHandler。

/**
 * 全局捕获Vue错误,直接扔出给onerror处理
 */
Vue.config.errorHandler = function (err) {
  setTimeout(() => {
    throw err
  })
}

React错误

react 通过componentDidCatch,声明一个错误边界的组件

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // 更新 state 使下一次渲染能够显示降级后的 UI
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // 你同样可以将错误日志上报给服务器
    logErrorToMyService(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // 你可以自定义降级后的 UI 并渲染
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}

class App extends React.Component {
   
  render() {
    return (
    <ErrorBoundary>
      <MyWidget />
    </ErrorBoundary>  
    )
  }
}

但error boundaries并不会捕捉以下错误:React事件处理,异步代码,error boundaries自己抛出的错误。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
el-admin后台管理系统是一个基于 Spring Boot 2.1.0 、 Spring boot Jpa、 Spring Security、redis、Vue的前后端分离的权限管理系统,项目采用分模块开发方式, 权限控制采用 RBAC(Role-Based Access Control,基于角色的访问控制),前端菜单支持动态路由。 el-admin后台管理系统特点: 1、使用最新技术栈,社区资源丰富。 2、高效率开发,代码生成器可一键生成前后端代码 3、支持数据字典,可方便地对一些状态进行管理 4、支持接口限流,避免恶意请求导致服务层压力过大 5、支持接口级别的功能权限与数据权限,可自定义操作 6、自定义权限注解与匿名接口注解,可快速对接口拦截与放行 7、对一些常用地前端组件封装:表格数据请求、数据字典等 8、前后端统一异常拦截处理,统一输出异常,避免繁琐的判断 9、支持在线用户管理与服务器性能监控,支持限制单用户登录 10、支持运维管理,可方便地对远程服务器的应用进行部署与管理 el-admin后台管理系统功能: 用户管理:提供用户的相关配置,新增用户后,默认密码为123456 角色管理:对权限与菜单进行分配,可根据部门设置角色的数据权限 菜单管理:已实现菜单动态路由,后端可配置化,支持多级菜单 部门管理:可配置系统组织架构,树形表格展示 岗位管理:配置各个部门的职位 字典管理:可维护常用一些固定的数据,如:状态,性别等 系统日志:记录用户操作日志与异常日志,方便开发人员定位拍错 SQL监控:采用druid 监控数据库访问性能,默认用户名admin,密码123456 定时任务:整合Quartz做定时任务,加入任务日志,任务运行情况一目了然 代码生成:高灵活度生成前后端代码,减少大量重复的工作任务 邮件工具:配合富文本,发送html格式的邮件 免费图床:使用sm.ms图床,用作公共图片上传使用,该图床不怎么稳定,不太建议使用 七牛云存储:可同步七牛云存储的数据到系统,无需登录七牛云直接操作云数据 支付宝支付:整合了支付宝支付并且提供了测试账号,可自行测试 服务监控:监控服务器的负载情况 运维管理:一键部署你的应用 用户账号密码 管理员:admin 测试用户:test 密码:123456 开发环境 JDK:8 IDE:IntelliJ IDEA (后端) IDE:JetBrains WebStorm (前端) 依赖管理:Maven 数据库:MySQL 5.5.59     el-admin后台管理系统 v2.6 更新日志: 本次升级解决了2.5版本中存在影响日常使用的问题,主要为菜单分配与缓存问题 优化 1、匿名接口SecurityConfig配置细腻化,支持不同类型的接口放行 2、验证码类型、长度、字体等参数可在配置文件中自定义 3、前端代码生成日期选择改为 date-range-picker 组件 4、Query 注解加入 INNER 查询,代码生成器细节优化 5、其他细节优化 修复 1、修复管理员修改用户的 username 后,用旧的用户名称还能登陆的问题 2、修复EncryptUtils 优化在linux中,存在解密乱码的情况 3、修复禁用用户后用户还可以操作的Bug 4、修复算数型验证码生成浮点型结果,导致前端输入整形数据匹配错误 5、修复菜单分配后菜单数据丢失的问题,修复缓存引起的一些问题
前端监控系统可以帮助我们监控网站的运行情况,及时发现异常,并给出相应的报警。其中,JS错误监控是其中的一个重要组成部分。本文将介绍如何搭建JS错误监控系统。 ## 1. 捕获JS错误 我们可以通过`window.onerror`事件来捕获JS错误。这个事件会在页面中任何一个未被`try-catch`捕获的JS错误发生时触发。我们可以在这个事件中获取到错误信息,并将其发送到后台进行处理。 ```javascript window.onerror = function (message, source, lineno, colno, error) { // message:错误信息 // source:错误文件的URL // lineno:错误所在行号 // colno:错误所在列号 // errorError对象 // 将错误信息发送到后台进行处理 // ... } ``` ## 2. 错误信息格式化 在捕获JS错误后,我们需要将错误信息进行格式化,以便后台能够更好地理解和处理。一般来说,我们可以将错误信息转换成JSON格式,并附带上一些额外的信息,如用户ID、设备信息等。 ```javascript function formatError(error) { return { message: error.message, // 错误信息 stack: error.stack, // 错误堆栈 url: window.location.href, // 页面URL user_agent: navigator.userAgent, // 用户设备信息 user_id: 'xxx' // 用户ID } } ``` ## 3. 发送错误信息 格式化完错误信息后,我们需要将其发送到后台进行处理。我们可以使用`XMLHttpRequest`或`fetch`来发送请求。 ```javascript function sendError(error) { var xhr = new XMLHttpRequest() xhr.open('POST', '/api/error', true) xhr.setRequestHeader('Content-Type', 'application/json') xhr.send(JSON.stringify(error)) } ``` ## 4. 完整代码 ```javascript window.onerror = function (message, source, lineno, colno, error) { var formattedError = formatError(error) sendError(formattedError) } function formatError(error) { return { message: error.message, stack: error.stack, url: window.location.href, user_agent: navigator.userAgent, user_id: 'xxx' } } function sendError(error) { var xhr = new XMLHttpRequest() xhr.open('POST', '/api/error', true) xhr.setRequestHeader('Content-Type', 'application/json') xhr.send(JSON.stringify(error)) } ``` 以上就是JS错误监控的基本实现方式。当然,我们可以根据具体需求对错误信息进行更加详细的处理和定制化的配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值