js毛病捕捉
js毛病的本质,也是发出一个事宜,处置惩罚他
error实例对象
对象属性
- message:毛病提醒信息
- name:毛病称号(非标准属性)宿主环境给予
- stack:毛病的客栈(非标准属性)宿主环境给予
对象范例(7种)
-
SyntaxError
对象是剖析代码时发作的语法毛病 -
ReferenceError
对象是援用一个不存在的变量时发作的毛病 -
RangeError
对象是一个值超越有用局限时发作的毛病(一是数组长度为负数,二是Number
对象的要领参数超越局限,以及函数客栈凌驾最大值) -
TypeError
对象是变量或参数不是预期范例时发作的毛病:对字符串、布尔值、数值等原始范例的值运用new
敕令 -
URIError
对象是 URI 相干函数的参数不准确时抛出的毛病:运用函数不当 -
eval
函数没有被准确实行时,会抛出EvalError
毛病 – 不再运用,为了代码兼容
-
自定义毛病
function UserError(message) { this.message = message || '默许信息'; this.name = 'UserError'; } UserError.prototype = new Error(); UserError.prototype.constructor = UserError; new UserError('这是自定义的毛病!');
Js运行时毛病处置惩罚机制
try..catch…finally
- 局限:用来捕捉任何范例的同步毛病,能够捕捉async / await的代码,但没法捕捉promise、setTimeout、dom回调(eg:onclick点击回调)的代码,在回调函数内里写try…catch能够捕捉,但包在表面不会捕捉,没法捕捉语法毛病
- 异步不捕捉缘由:
- async/await捕捉缘由:
window.onerror
- 局限:同步毛病和异步毛病都能够捕捉,但没法捕捉到静态资本非常,或许接口非常(收集要求非常不会事宜冒泡,因而必须在捕捉阶段将其捕捉到才行),没法捕捉语法毛病
- 道理:当
JS
运行时毛病发作时,window
会触发一个ErrorEvent
接口的error
事宜 参数
/** * @param {String} message 毛病信息 * @param {String} source 失足文件 * @param {Number} lineno 行号 * @param {Number} colno 列号
*/
window.onerror = function(message, source, lineno, colno, error) {
console.log('捕捉到非常:',{message, source, lineno, colno, error});
}
```
- 补充:window.onerror
函数只要在返回
true的时刻,非常才不会向上抛出,不然即使是晓得非常的发作控制台照样会显现
Uncaught Error: xxxxx -
onerror
最好写在一切JS
剧本的前面,不然有能够捕捉不到毛病;(捕捉的是全局毛病)
资本加载毛病
- window.addEventListener(一项资本(如图片或剧本)加载失利,加载资本的元素会触发一个
Event
接口的error
事宜,并实行该元素上的onerror()
处置惩罚函数,有浏览器兼容题目) 注重:只能捕捉没法冒泡
window.addEventListener('error', (error) => { console.log('捕捉到非常:', error); }, true) // 一定要加true,捕捉但不冒泡
Script error跨域的静态资本加载非常捕捉(cdn文件等)
跨域文件只会报Script error,没有细致信息,怎样处理:
- 客户端:script标签增添crossOrigin
- 效劳端:设置:Access-Control-Allow-Origin
<script src="http://jartto.wang/main.js" crossorigin></script>
iframe非常
运用window.onerror
<iframe src="./iframe.html" frameborder="0"></iframe> <script> window.frames[0].onerror = function (message, source, lineno, colno, error) { console.log('捕捉到 iframe 非常:',{message, source, lineno, colno, error}); return true; }; </script>
promise非常捕捉
- 没有写
catch
的Promise
中抛出的毛病没法被onerror
或try-catch
捕捉到 为了防备有遗漏的
Promise
非常,发起在全局增添一个对unhandledrejection
的监听,用来全局监听Uncaught Promise Error
window.addEventListener("unhandledrejection", function(e){ console.log(e); });
- 补充:假如去掉控制台的非常显现,须要加上:event.preventDefault();
vue非常捕捉
VUE errorHandler
Vue.config.errorHandler = (err, vm, info) => { console.error('经由过程vue errorHandler捕捉的毛病'); console.error(err); console.error(vm); console.error(info); }
React非常捕捉
- componentDidCatch(React16)
新概念Error boundary(React16):UI的某部份激发的
JS
毛病不会损坏全部顺序(只要 class component
能够成为一个error boundaries
)不会捕捉以下毛病
1.事宜处置惩罚器 2.异步代码 3.效劳端的衬着代码 4.在 error boundaries 地区内的毛病
Eg: 全局一个
error boundary
组件就够用啦class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, info) { // Display fallback UI this.setState({ hasError: true }); // You can also log the error to an error reporting service logErrorToMyService(error, info); } render() { if (this.state.hasError) { // You can render any custom fallback UI return <h1>Something went wrong.</h1>; } return this.props.children; } } <ErrorBoundary> <MyWidget /> </ErrorBoundary>
页面崩溃和卡顿处置惩罚
卡顿
- 网页临时相应比较慢,
JS
能够没法及时实行 处理:
window
对象的load
和beforeunload
事宜完成了网页崩溃的监控window.addEventListener('load', function () { sessionStorage.setItem('good_exit', 'pending'); setInterval(function () { sessionStorage.setItem('time_before_crash', new Date().toString()); }, 1000); }); window.addEventListener('beforeunload', function () { sessionStorage.setItem('good_exit', 'true'); }); if(sessionStorage.getItem('good_exit') && sessionStorage.getItem('good_exit') !== 'true') { /* insert crash logging code here */ alert('Hey, welcome back from your crash, looks like you crashed on: ' + sessionStorage.getItem('time_before_crash')); }
- 网页临时相应比较慢,
崩溃
-
JS
都不运行了,另有什么方法能够监控网页的崩溃,并将网页崩溃上报呢 处理:
Service Worker
来完成网页崩溃的监控-
Service Worker
有自身自力的事情线程,与网页区离开,网页崩溃了,Service Worker
平常情况下不会崩溃; -
Service Worker
生命周期平常要比网页还要长,能够用来监控网页的状况; - 网页能够经由过程
navigator.serviceWorker.controller.postMessage API
向掌管自身的SW
发送音讯。
-
-
毛病上报机制
-
Ajax
发送数据
因为Ajax
要求自身也有能够会发作非常,而且有能够会激发跨域题目,平常情况下更引荐运用动态建立img
标签的情势举行上报。 - 动态建立
img
标签的情势 更经常使用,简朴,无逾越题目
function report(error) {
let reportUrl = 'http://jartto.wang/report';
new Image().src = `${reportUrl}?logs=${error}`;
}
- 假如你的网站访问量很大,那末一个必定的毛病发送的信息就有很多条,这时刻,我们须要设置收集率,从而减缓效劳器的压力:
Reporter.send = function(data) {
// 只收集 30%
if(Math.random() < 0.3) {
send(data) // 上报毛病信息
}
}
js源代码紧缩怎样定位:成熟计划供应sentry
sentry 是一个及时的毛病日记追踪和聚合平台,包含了上面 sourcemap 计划,并支撑更多功用,如:毛病挪用栈,log 信息,issue治理,多项目,多用户,供应多种语言客户端等,
这里不过量叙说,以后在搭建sentry效劳时,会再补篇博文
补充:node效劳端毛病处置惩罚机制
全栈开辟,后端采纳express库,在这里补充一下,node效劳的毛病处置惩罚计划
毛病分类
- 平常毛病处置惩罚:如某种回退,基本上只是说:“有毛病,请再试一次或联络我们”。这并非迥殊智慧,但至少关照用户,有处所错了——而不是无穷加载或举行相似地处置惩罚
- 特别毛病处置惩罚为用户供应细致信息,让用户相识有什么题目以及怎样处理它,比方,有信息丧失,数据库中的条目已存在等等
步骤
1. 构建一个自定义 Error 组织函数:让我们方便地取得客栈跟踪
class CustomError extends Error { constructor(code = 'GENERIC', status = 500, ...params) { super(...params) if (Error.captureStackTrace) { Error.captureStackTrace(this, CustomError) } this.code = code this.status = status } } module.exports = CustomError
2.处置惩罚路由:关于每个路由,我们要有雷同的毛病处置惩罚行动
wT:在默许情况下,因为路由都是封装的,所以 Express 并不真正支撑那种体式格局
处理:完成一个路由处置惩罚顺序,并把现实的路由逻辑定义为一般的函数。如许,假如路由功用(或任何内部函数)抛出一个毛病,它将返回到路由处置惩罚顺序,然后能够传给前端
const express = require('express') const router = express.Router() const CustomError = require('../CustomError') router.use(async (req, res) => { try { const route = require(`.${req.path}`)[req.method] try { const result = route(req) // We pass the request to the route function res.send(result) // We just send to the client what we get returned from the route function } catch (err) { /* This will be entered, if an error occurs inside the route function. */ if (err instanceof CustomError) { /* In case the error has already been handled, we just transform the error to our return object. */ return res.status(err.status).send({ error: err.code, description: err.message, }) } else { console.error(err) // For debugging reasons // It would be an unhandled error, here we can just return our generic error object. return res.status(500).send({ error: 'GENERIC', description: 'Something went wrong. Please try again or contact support.', }) } } } catch (err) { /* This will be entered, if the require fails, meaning there is either no file with the name of the request path or no exported function with the given request method. */ res.status(404).send({ error: 'NOT_FOUND', description: 'The resource you tried to access does not exist.', }) } }) module.exports = router // 现实路由文件 const CustomError = require('../CustomError') const GET = req => { // example for success return { name: 'Rio de Janeiro' } } const POST = req => { // example for unhandled error throw new Error('Some unexpected error, may also be thrown by a library or the runtime.') } const DELETE = req => { // example for handled error throw new CustomError('CITY_NOT_FOUND', 404, 'The city you are trying to delete could not be found.') } const PATCH = req => { // example for catching errors and using a CustomError try { // something bad happens here throw new Error('Some internal error') } catch (err) { console.error(err) // decide what you want to do here throw new CustomError( 'CITY_NOT_EDITABLE', 400, 'The city you are trying to edit is not editable.' ) } } module.exports = { GET, POST, DELETE, PATCH, }
3.构建全局毛病处置惩罚机制
process.on('uncaughtException', (error: any) => { logger.error('uncaughtException', error) }) process.on('unhandledRejection', (error: any) => { logger.error('unhandledRejection', error) })
总结:
1.可疑地区增添 Try-Catch
2.全局监控 JS
非常 window.onerror
3.全局监控静态资本非常 window.addEventListener
4.捕捉没有 Catch
的 Promise
非常:unhandledrejection
5.VUE errorHandler
和 React componentDidCatch
6.监控网页崩溃:window
对象的 load
和 beforeunload
7.跨域 crossOrigin
处理