传统的前端页面错误捕获直接使用
window.onerror = function (msg, url, lineNo, columnNo, error) { console.log(msg) console.log(url) }window.addEventListener('error', (msg, url, row, col, error) => { console.log('我知道错了') console.log(msg, url, row, col, error) return true }, true)复制代码
这样就可以实现大部分错误的捕获,但是在MVVM时代这样的捕获方式不可行的,因为无论是Vue还是React都有自己捕获错误的方法,在Vue中,其本身提供了一种方式进行Vue页面的错误捕获
Vue.config.errorHandler = function (err, vm, info) { if (vm) { let componentName = formatComponentName(vm); let propsData = vm.$options && vm.$options.propsData; console.log(componentName) console.log(propsData) let { message, // 异常信息 name, // 异常名字 script, // 异常脚本url line, // 异常行号 colum, // 异常列号 stack // 异常堆栈信息 } = err console.log(stack) } else { } };复制代码
我们查看Vue相关的源码时可以发现为什么传统的错误捕获方式对Vue不适用,源码目录vue/src/core/util/error.js
function globalHandleError (err, vm, info) { if (config.errorHandler) { try { return config.errorHandler.call(null, err, vm, info) } catch (e) { logError(e, null, 'config.errorHandler') } } logError(err, vm, info)}function logError (err, vm, info) { if (process.env.NODE_ENV !== 'production') { warn(`Error in ${info}: "${err.toString()}"`, vm) } /* istanbul ignore else */ if ((inBrowser || inWeex) && typeof console !== 'undefined') { console.error(err) } else { throw err }}复制代码
从中我们可以看到没有被Vue捕获到的错误会以console.error(err)的方式抛出来,所以我们无论采用window.onerror还是采用window.addEventListener('error')的方式都是捕获不到任何错误的,但是Vue提供只能捕获其页面生命周期内的函数,比如created,mounted等等,从 2.4.0 起这个钩子也会捕获 Vue 自定义事件处理函数内部的错误了,所谓的自定义就是在生命周期钩子内调用的函数,如果一个函数不被生命周期钩子引用一旦报错,Vue是捕获不到的,这时就需要使用传统的错误捕获方式进行捕获了。
捕获网络请求相关错误
由于网络请求异常不会事件冒泡,因此必须在捕获阶段将其捕捉才行,但是这种方式虽然可以捕捉到网络请求的异常,但是无法判断HTTP的转态是404,还是500d等等,所以要想具体查相关请求的HTTP状态还是需要配合服务端日志才行
window.addEventListener('error', (msg, url, row, col, error) => { console.log('我知道错了') console.log(msg, url, row, col, error) return true }, true)复制代码
我们可以通过这种错误捕获的方式捕获一些资源加载错误相关信息
捕获Promise错误
一旦Promise实例抛出异常而你没有用catch去捕获的话,onerror或try-catch也无能为力,无法捕获到错误,这时我们可以采用window.addEventListener('unhandledrejection', function(e) { e.preventDefault() console.log('这是Promise的错误') console.log(e.reason) return true })复制代码
进行promise相关错误的捕获
捕获ajax,axios,fetch等接口请求错误
直接在请求发送期和响应期对数据进行劫持// 请求劫持axios.interceptors.request.use(config=> { return config;}, err=> { Message.error({message: '请求超时!'}); return Promise.resolve(err);})// 响应劫持axios.interceptors.response.use(data=> { if (data.status && data.status == 200 && data.data.status == 'error') { Message.error({message: data.data.msg}); return; } return data;}, err=> { if (err.response.status == 504||err.response.status == 404) { Message.error({message: '服务器被吃了⊙﹏⊙∥'}); } else if (err.response.status == 403) { Message.error({message: '权限不足,请联系管理员!'}); }else { Message.error({message: '未知错误!'}); } return Promise.resolve(err);})复制代码
然后进行收到收集上报到日志系统