目录 Q1. 同步代码里的错误捕获方式 Q2. 普通的异步回调里的错误捕获方式(Promise时代以前) Q3. Promise里的错误捕获方式 Q4.async/await里的错误捕获方式 Q5.在全局环境下如何监听错误 Q6.在React16以上如何监听错误 Sentry简单介绍 在JavaScript中使用Sentry Sentry的核心功能总结 正文 怎么捕获错误并且处理,是一门语言必备的知识。在JavaScript中也是如此。 那怎么捕获错误呢?初看好像很简单,try-catch就可以了嘛!但是有的时候我们发现情况却繁多复杂。 Q1: 同步可以try-catch,但一个异步回调,比如setTimeOut里的函数还可以try-catch吗? Q2: Promise的错误捕获怎么做? Q3: async/await怎么捕获错误? Q4: 我能够在全局环境下捕获错误并且处理吗? Q5: React16有什么新的错误捕获方式吗? Q6: 捕获之后怎么上报和处理? 问题有点多,我们一个一个来。 回到顶部 Q1. 同步代码里的错误捕获方式 在同步代码里,我们是最简单的,只要try-catch就完了 复制代码 function test1 () { try { throw Error ('callback err'); } catch (error) { console.log ('test1:catch err successfully'); } } test1(); 复制代码 输出结果如下,显然是正常的 回到顶部 Q2. 普通的异步回调里的错误捕获方式(Promise时代以前) 上面的问题来了,我们还能通过直接的try-catch在异步回调外部捕获错误吗?我们试一试 复制代码 // 尝试在异步回调外部捕获错误的结果 function test2 () { try { setTimeout (function () { throw Error ('callback err'); }); } catch (error) { console.log ('test2:catch err successfully'); } } test2(); 复制代码 输出 注意这里的Uncaught Error的文本,它告诉我们错误没有被成功捕捉。 为什么呢? 因为try-catch的是属于同步代码,它执行的时候,setTimeOut内部的的匿名函数还没有执行呢。而内部的那个匿名函数执行的时候,try-catch早就执行完了。( error的内心想法:哈哈,只要我跑的够慢,try-catch还是追不上我!) 但是我们简单想一想,诶我们把try-catch写到函数里面不就完事了嘛! 复制代码 function test2_1 () { setTimeout (function () { try { throw Error ('callback err'); } catch (error) { console.log ('test2_1:catch err successfully'); } }); } test2_1(); 复制代码 输出结果如下,告诉我们这方法可行 总结下Promise时代以前,异步回调中捕获和处理错误的方法 在异步回调内部编写try-catch去捕获和处理,不要在外部哦 很多异步操作会开放error事件,我们根据事件去操作就可以了 回到顶部 Q3. Promise里的错误捕获方式 可通过Promise.catch方法捕获 复制代码 function test3 () { new Promise ((resolve, reject) => { throw Error ('promise error'); }).catch (err => { console.log ('promise error'); }); } 复制代码 输出结果 >> reject方法调用和throw Error都可以通过Promise.catch方法捕获 复制代码 function test4 () { new Promise ((resolve, reject) => { reject ('promise reject error'); }).catch (err => { console.log (err); }); } 复制代码 输出结果 >> then方法中的失败回调和Promise.catch的关系 如果前面的then方法没写失败回调,失败时后面的catch是会被调用的 如果前面的then方法写了失败回调,又没抛出,那么后面的catch就不会被调用了 复制代码 // then方法没写失败回调 function test5 () { new Promise ((resolve, reject) => { throw Error ('promise error'); }) .then (success => {}) .catch (err => { console.log ('the error has not been swallowed up'); }); } // then方法写了失败回调 function test5 () { new Promise ((resolve, reject) => { throw Error ('promise error'); }) .then (success => {},err => {}) .catch (err => { console.log ('the error has not been swallowed up'); }); } 复制代码 输出分别为 1.the error has not been swallowed up 2.无输出 回到顶部 Q4.async/await里的错误捕获方式 对于async/await这种类型的异步,我们可以通过try-catch去解决 复制代码 async function test6 () { try { await getErrorP (); } catch (error) { console.log ('async/await error with throw error'); } } function getErrorP () { return new Promise ((resolve, reject) => { throw Error ('promise error'); }); } test6(); 复制代码 输出结果如下 >> 如果被await修饰的Promise因为reject调用而变化,它也是能被try-catch的 (我已经证明了这一点,但是这里位置不够,我写不下了) 回到顶部 Q5.在全局环境下如何监听错误 window.onerror可以监听全局错误,但是很显然错误还是会抛出 复制代码 window.onerror = function (err) { console.log ('global error'); }; throw Error ('global error'); 复制代码 输出如下 回到顶部 Q6.在React16以上如何监听错误 >> componentDidCatch和getDerivedStateFromError钩子函数 复制代码 class Bar extends React.Component { // 监听组件错误 componentDidCatch(error, info) { this.setState({ error, info }); } // 更新 state 使下一次渲染能够显示降级后的 UI static getDerivedStateFromError(error) { return { hasError: true }; } render() { } } 复制代码 有错误,那肯定要上报啊!不上报就发现不了Bug这个样子。Sentry这位老哥就是个人才,日志记录又好看,每次见面就像回家一样 回到顶部 Sentry简单介绍 Sentry provides open-source and hosted error monitoring that helps all software teams discover, triage, and prioritize errors in real-time. One million developers at over fifty thousand companies already ship better software faster with Sentry. Won’t you join them? —— Sentry官网 Sentry是一个日志上报系统,Sentry 是一个实时的日志记录和汇总处理的平台。专注于错误监控,发现和数据处理,可以让我们不再依赖于用户反馈才能发现和解决线上bug。让我们简单看一下Sentry支持哪些语言和平台吧 在JavaScript领域,Sentry的支持也可以说是面面俱到 参考链接 https://docs.sentry.io/platforms/ Sentry的功能简单说就是,你在代码中catch错误,然后调用Sentry的方法,然后Sentry就会自动帮你分析和整理错误日志,例如下面这张图截取自Sentry的网站中 回到顶部 在JavaScript中使用Sentry 1.首先呢,你当然要注册Sentry的账号 这个时候Sentry会自动给你分配一个唯一标示,这个标示在Sentry里叫做 dsn 2. 安卓模块并使用基础功能 安装@sentry/browser npm install @sentry/browser 在项目中初始化并使用 复制代码 import * as Sentry from '@sentry/browser'; Sentry.init ({ dsn: 'xxxx', }); try { throw Error ('我是一个error'); } catch (err) { // 捕捉错误 Sentry.captureException (err); } 复制代码 3.上传sourceMap以方便在线上平台阅读出错的源码 复制代码 // 安装 $ npm install --save-dev @sentry/webpack-plugin $ yarn add --dev @sentry/webpack-plugin // 配置webpack const SentryWebpackPlugin = require('@sentry/webpack-plugin'); module.exports = { // other configuration plugins: [ new SentryWebpackPlugin({ include: '.', ignoreFile: '.sentrycliignore', ignore: ['node_modules', 'webpack.config.js'], configFile: 'sentry.properties' }) ] }; 复制代码 4. 为什么不是raven.js? 复制代码 // 已经废弃,虽然你还是可以用 var Raven = require('raven-js'); Raven .config('xxxxxxxxxxx_dsn') .install(); 复制代码 回到顶部 Sentry的核心功能总结 捕获错误 复制代码 try { aFunctionThatMightFail(); } catch (err) { Sentry.captureException(err); } 复制代码 设置该错误发生的用户信息 下面每个选项都是可选的,但必须 存在一个选项 才能使Sentry SDK捕获用户: id 复制代码 Sentry.setUser({ id:"penghuwan12314" email: "penghuwan@example.com", username:"penghuwan", ip_addressZ:'xxx.xxx.xxx.xxx' }); 复制代码 设置额外数据 Sentry.setExtra("character_name", "Mighty Fighter"); 设置作用域 复制代码 Sentry.withScope(function(scope) { // 下面的set的效果只存在于函数的作用域内 scope.setFingerprint(['Database Connection Error']); scope.setUser(someUser); Sentry.captureException(err); }); // 在这里,上面的setUser的设置效果会消失 复制代码 设置错误的分组 整理日志信息,避免过度冗余 复制代码 Sentry.configureScope(function(scope) { scope.setFingerprint(['my-view-function']); }); 复制代码 设置错误的级别 在阅读日志时可以确定各个bug的紧急度,确定排查的优先书序 复制代码 Sentry.captureMessage('this is a debug message', 'debug'); //fatal,error,warning,info,debug五个值 // fatal最严重,debug最轻 复制代码 自动记录某些事件 例如下面的方法,会在每次屏幕调整时完成上报 复制代码 window.addEventListener('resize', function(event){ Sentry.addBreadcrumb({ category: 'ui', message: 'New window size:' + window.innerWidth + 'x' + window.innerHeight, level: 'info' }); }) 复制代码 Sentry实践的运用 根据环境设置不同的dsn 复制代码 let dsn; if (env === 'test') { dsn = '测试环境的dsn'; } else { dsn = '正式环境的dsn'; } Sentry.init ({ dsn }); 复制代码https://www.cnblogs.com/penghuwan/p/11905429.html