在开发工作中难免会出现bug,一般项目都是测试检查通过后就可以发线上,可是在线上仍旧会出现各种意料之外或者未测试到的问题,这个时候有的用户会向客服反馈说哪里哪里有问题,这是一种被动的错误上报方式,毕竟不是所有的用户都会上报问题,更多的则是出现问题后直接离开我们的APP。所以异常监控这块就显得越来越重要。
页面异常分类
在我们的项目中我将页面异常分为以下几种情况:
- javascript异常(语法错误,运行时错误,跨域脚本)
- 资源加载异常(img js css)
- ajax请求异常
- promise异常
- vue项目中全局异常捕获
接下来介绍如何捕获这些异常
前端页面异常捕获方式
window.onerror捕获javascript异常
/** * 捕获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 }); }
跨域脚本异常捕获
一般涉及跨域的js运行错误时会抛出错误提示script error.,但没有具体信息(如出错文件,行列号提示等), 可利用资源共享策略来捕获跨域js错误
客户端:在script标签增加crossorigin="anonymous"属性
服务端:静态资源响应头Access-Control-Allow-Origin: *
window.addEventListener('error',cb,true)捕获资源加载异常
img加载异常时会触发img.onerror函数
// 捕获资源加载异常 window.addEventListener('error',function(e){ const err = e.target.src || e.target.href if(err){ console.log('捕获到资源加载异常',err) } },true)
ajax接口请求异常捕获
// 统一拦截ajax请求 var startTime = 0 var gapTime = 0 // 计算请求延时 window.addEventListener('ajaxReadyStateChange', function (e) { var xhr = e.detail var status = xhr.status var readyState = xhr.readyState /** * 计算请求延时 */ if (readyState === 1) { startTime = (new Date()).getTime() } if (readyState === 4) { gapTime = (new Date()).getTime() - startTime } /** * 上报请求信息 */ if (readyState === 4) { if(status === 200){ // 接口正常响应时捕获接口响应耗时 console.log('接口',xhr.responseURL,'耗时',gapTime) }else{ // 接口异常时捕获异常接口及状态码 console.log('异常接口',xhr.responseURL,'状态码',status) } } })
promise异常捕获
promise 中的报错顺序是:
如果有catch 等捕获函数,则走catch 捕获函数。catch 捕获函数如果没有抛出新的异常,则下一个then将会认为没有什么报错,会继续执行。
如果没有catch 等捕获函数,我们需要注册 window.addEventListener('unhandledrejection') 来处理
/** * Promise catch错误上报,需要在使用promise的地方显示调用.catch(),否则不会捕获错误 */ if (typeof Promise !== 'undefined') { var _promiseCatch = Promise.prototype.catch Promise.prototype.catch = function (foo) { return _promiseCatch.call(this, catCatch(foo)) } } function catCatch (foo) { return function (args) { let msg = args.stack ? args.stack : args console.log('捕获到catch中的异常',msg) foo && foo.call(this, args) } } /** * 监听promise未处理的reject错误, 跨域情况下监控不到 */ window.addEventListener('unhandledrejection', event => { console.log('捕获到未处理的promise异常',event.reson) })
vue项目全局异常捕获
Vue.config.errorHandler = function (err, vm, info) { // `info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子 // 只在 2.2.0+ 可用 let msg = `错误发生在:${info}中,具体信息:${err.stack}` console.log(msg) }
捕获到这些异常后我们需要将这些异常上报给服务器,我们直接以请求图片的形式发送上报内容
异常上报
function report (msg) { var reportUrl = 'http://xxxx/report' new Image().src = reportUrl + encodeURIComponent(JSON.stringify(msg)) }
来源:https://www.cnblogs.com/jesse131/p/12179106.html