- [生存指南]面试题(3): 如何做前端sentry性能监控中的错误和数据采集
[图片] 随着 “大前端” 近两年愈演愈烈(juan),需要我们掌握的技能也越来越多,延伸而来的就是各种前端性能和异常监控框架。 市面上有很多种开源的框架,如 Sentry、Rollbar 等,大厂也会自己建立一套完整的监控体系,有时候还会配合后端的ELK系统一起使用,无论用什么框架,最关键的一步就是:前期的 数据采集和错误捕获, 这里为大家简单分享下一些主流的方式。 1、代码异常捕获 try-catch [代码]try { // Some code that may throw an error } catch (error) { //发送错误信息 console.log(error); //sendError(error) } [代码] 相信大家在一些关键的同步请求的时候,会用上try-catch,避免因为报错,导致整个功能弹出,这也是常规用来捕捉错误日志的方法。 在前端中使用try-catch语句可以帮助开发人员及时发现和解决错误,提高应用程序的健壮性和稳定性。同时,使用第三方错误监控工具可以自动化地收集和汇总错误信息,减少手动调试和排查错误的工作量。 2、页面监控window.onerror [代码] /** * @param {String} errorMessage 错误信息 * @param {String} scriptURI 出错的文件 * @param {Long} lineNumber 出错代码的行号 * @param {Long} columnNumber 出错代码的列号 * @param {Object} errorObj 错误的详细信息,Anything */ window.onerror = function(errorMessage, scriptURI, lineNumber,columnNumber,errorObj) { console.log("错误信息:" , errorMessage); console.log("出错文件:" , scriptURI); console.log("出错行号:" , lineNumber); console.log("出错列号:" , columnNumber); console.log("错误详情:" , errorObj); } [代码] 这种错误监听,可以获取同步和异步的方法,也是比较实用,且常规的一种错误监听的方法,此外,还能提供详尽的数据位置,地址等 3、异常捕获(addEventListener) window.addEventListener(“error”) [代码]// 监听 JavaScript 异常 window.addEventListener('error', function(event) { // 收集错误信息 const error = { message: event.message, filename: event.filename, lineno: event.lineno, colno: event.colno, error: event.error, }; //发送错误信息 }); //图片加载错误监听 image.addEventlistener("error",e => ( e.preventDefault(); //发送错误信息 console.log(e); } // 监听 JavaScript 文件的加载状态 const script = document.createElement('script'); script.addEventListener('load', function(event) { // JavaScript 文件加载完成 console.log('JavaScript file loaded'); }); script.addEventListener('error', function(event) { // JavaScript 文件加载失败 console.error('JavaScript file failed to load'); }); script.src = 'path/to/javascript/file.js'; document.head.appendChild(script); // 监听 CSS 文件的加载状态 const link = document.createElement('link'); link.addEventListener('load', function(event) { // CSS 文件加载完成 console.log('CSS file loaded'); }); link.addEventListener('error', function(event) { // CSS 文件加载失败 console.error('CSS file failed to load'); }); link.rel = 'stylesheet'; link.href = 'path/to/css/file.css'; document.head.appendChild(link); [代码] 也可以用另外一个省代码的写法 [代码]// 监听处理js/css window .addEventListener("error", function (e) { var typeName = e.target.localName; var sourceUrl = ""; if(typeName === "link"){ sourceUrl = e.target.href; }else if(typeName === 'script'){ sourceUrl = e.target.src; } //发送错误信息 }); [代码] 使用 addEventListener 来监听 JavaScript 和 CSS 文件的加载状态可以帮助开发者及时发现和解决加载问题,提高应用程序的稳定性和可靠性,从而提升用户体验和满意度。 window.addEventListener(“unhandledrejection”) [代码]window.addEventListener("unhandledrejection", function(event) { // 阻止默认行为,防止 Promise 异常被浏览器捕获并输出到控制台 event.preventDefault(); // 收集 Promise 异常信息 const error = { message: event.reason.message, stack: event.reason.stack, }; // 将异常信息发送到服务器或其他地方进行分析和报告 sendErrorData(error); }); [代码] 在上面的代码中,我们使用 window.addEventListener(“unhandledrejection”) 方法来监听未处理的 Promise 异常,并收集异常信息。当 Promise 被拒绝时,会触发 unhandledrejection 事件,并将异常信息作为事件参数传递给回调函数。然后我们将异常信息发送到服务器或其他地方进行分析和报告。 需要注意的是,当 Promise 对象被拒绝时,浏览器会默认输出异常信息到控制台。为了防止 Promise 异常被浏览器捕获并输出到控制台,我们需要在回调函数中调用 event.preventDefault() 方法,阻止默认行为的发生。 使用 window.addEventListener(“unhandledrejection”) 方法来监听 JavaScript Promise 的拒绝状态可以帮助开发者及时发现和解决异常问题,提高应用程序的稳定性和可靠性,从而提升用户体验和满意度。 4、性能监听(Performance) 可以使用 Performance API 来做监听 [代码]// 初始化 Performance API const perf = window.performance; // 创建一个新的性能条目 const entry = perf.mark('start'); // 在某个时间点开始执行某段代码 const startTime = performance.now(); // 在某个时间点结束执行某段代码 const endTime = performance.now(); // 收集性能数据 const data = { duration: endTime - startTime, // 其他性能指标,如占用 CPU 时间、内存使用等等 }; // 将性能数据发送到服务器或其他地方进行分析和报告 [代码] Performance API 是浏览器提供的一组 API,用于监测前端应用程序的性能指标,帮助开发者发现性能问题并进行优化。Performance API 提供了多个方法和属性,可以监测页面加载时间、资源加载时间、代码执行时间、内存使用情况、帧率等等性能指标。 以下是 Performance API 中常用的一些方法和属性: performance.mark(name):创建一个新的性能条目,并在当前时间点标记该条目。 performance.measure(name, startMarkName,endMarkName):在两个标记点之间测量性能,并创建一个新的性能条目。 performance.getEntries():返回所有的性能条目。 performance.getEntriesByName(name):返回指定名称的性能条目。 performance.now():返回当前时间点的时间戳,精度为毫秒。 performance.timing:返回页面加载时间的性能指标,包括 DNS 查询时间、TCP 连接时间、请求时间、响应时间等等。 5、框架层面的错误捕获 VUE: Vue.config.errorHandler Vue.config.errorHandler 是 Vue.js 提供的一个全局错误处理器,用于捕获 Vue.js 应用程序中的未处理异常。以下是一个例子,演示如何使用 Vue.config.errorHandler 捕获 Vue.js 应用程序中的未处理异常: [代码]Vue.config.errorHandler = function(err, vm, info) { // 收集异常信息 const errorData = { message: err.message, stack: err.stack, info: info, }; // 将异常信息发送到服务器或其他地方进行分析和报告 sendError(errorData) }; [代码] React: ErrorBoundary React 的 ErrorBoundary 是 React 提供的一个组件,用于捕获 React 应用程序中的未处理异常。以下是一个例子,演示如何使用 ErrorBoundary 捕获 React 应用程序中的未处理异常: [代码]class MyErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, info) { // 收集异常信息 const errorData = { message: error.message, stack: error.stack, info: info, }; // 将异常信息发送到服务器或其他地方进行分析和报告 sendError(errorData); } render() { if (this.state.hasError) { return <h1>出错了!</h1>; } return this.props.children; } } [代码] 我们使用 ErrorBoundary 组件来捕获 React 应用程序中的未处理异常,并收集异常信息。当 React 应用程序发生未处理异常时,会触发 componentDidCatch 事件,并将异常信息作为事件参数传递给回调函数。然后我们将异常信息发送到服务器或其他地方进行分析和报告。
2023-07-25 - 如何彻底解决小程序滚动穿透问题
背景 俗话说,产品有三宝:弹窗、浮层加引导,足以见弹窗在产品同学心目中的地位。对任意一个刚入门的前端同学来说,实现一个模态框基本都可以达到信手拈来的地步,但是,当模态框里边的内容滚动起来以后,就会出现各种各样的让人摸不着头脑的问题,其中,最出名的想必就是滚动穿透。 什么是滚动穿透? 滚动穿透的定义:指我们滑动顶层的弹窗,但效果上却滑动了底层的内容。 具体解决方案分析如下: 改变顶层:从穿透的思路考虑,如果顶层不会穿透过去,那么问题就解决了,所以我们尝试给蒙层加catchtouchmove,但是发现部分场景无效果,那么就不再赘述了。 改变底层:既然是顶层影响了底层,要是底层不会滚动,那就没这个问题了。 如何改变底层解决该问题呢? 不成熟方案: 底部页面最外层view设置position: fixed;页面不可滚动,但是这个时候会导致页面回到顶部。 滚动时监听滚动距离,弹窗时记录滚动位置,关闭弹窗后使用wx.pageScrollTo回滚到记录的位置。 成熟方案 使用page-meta组件,通过该组件我们可以操作Page的style样式,类似于h5里body设置overflow: hidden; 控制页面不可滚动。文档地址:https://developers.weixin.qq.com/miniprogram/dev/component/page-meta.html 使用wx.setPageStyle设置overflow: hidden, 也可以实现给Page组件设置样式。) page-meta组件: 通过该组件我们可以直接操作[代码]Page[代码]组件 ,我们给它的wxss样式overflow动态设置[代码]hidden[代码]or[代码]visible[代码]or[代码]auto[代码] 就可以控制整个页面是否可以滚动。 [图片] wx.setPageStyle方法: 调用这个api,动态设置它为hidden/auto,用于控制页面是否可滚动,主要用于页面组件内使用,比如封装好的弹窗组件,就不用单独写page-meta组件了。。 [代码]wx.setPageStyle({ style: { overflow: 'hidden' // ‘auto’ } }) [代码] 老规矩,结尾放代码片段: https://developers.weixin.qq.com/s/U6ItgQmP7upQ 拓展 支付宝小程序虽然存在page-meta组件,但是由于内核为69版本,给page设置overflow: hidden 也无法控制底部元素不可滚动,目前已联系支付宝的底层开发同学提供API控制页面disableScroll,目前正在封装Appx,近期开放。
08-06 - getPhoneNumber|agreePrivacyAuthorization无效?
从基础库 2.33.1 版本起,该组件支持与手机号快速验证组件、手机号实时验证组件耦合使用,调用方式为 <button open-type="getPhoneNumber|agreePrivacyAuthorization"> 这个没用啊 单个agreePrivacyAuthorization倒是可以 [图片] [图片]
2023-08-16 - 刚收到通知获取手机号收费开始了?
[图片] https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getRealtimePhoneNumber.html https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/paymentManage.html 未来:旧版本接口依然可以使用,只是需要收费而已,不想做改动的交钱就行了。如果想用新API方法就去改吧,多花一分钱。 可能支持的省钱办法: 授权手机号后,服务端将openId、手机号进行绑定。用户onLaunch打开小程序的时候通过wx.login获取code去解密openId,同时由于服务端已经绑定过手机号,所以可以使用该手机号进行登录,并同步返回token、jwtToken等登录态。这样可以做到用户冷启动小程序时自动登录上,减少使用授权的逻辑。业务按钮点击后 先调用wx.login,如果返回token则进行后续业务,如果没返回则弹出自定义弹窗,弹窗内点击按钮再进行手机号授权。(也可以在部分页面onLoad里wx.login),这个场景因为会延长流程,所以产品说不考虑,先直接打开页面就登录上,你们的各自看各自的业务场景吧。然后有四个疑问: 充值购买次数后会,如果小程序被封禁了,充值的金额是否可退款。购买数量是否支持按量付费?如果次数用完了,未购买新的次数,用户端的表现是什么?如果次数用完了,之前文档说的余量20%、10%、5%时会发模板消息提醒,文档相关现在已经删除了,是否还会发?[图片] ———————————————————————————————————————————————— 今天看了下文档做了改动: 退款规则:若购买有误,且未正式开始使用资源包前,可以在支付成功后的7天内申请退款。款项将在3-5个工作日内从原支付路径返回;若资源包已经开始使用(使用1次及以上),则不能申请退款;若支付成功后超过7天,未发起退款申请,亦不能再申请退款。 那么小程序被封了应该是不退的。不确定,等官方回复次数用完了,用户授权不会弹出授权弹窗,会返回一个errNo:1400001,用户判断等于这个errNo的时候跳转到自己的账密登录页面。不确定,等官方回复———————————————————————————————————————————————— 据了解老版本的快速验证组件(获取手机号),180天才会发送短信验证一次,为啥能每次授权都收费0.03元。 社区搜了一张图,180天没验证的应该会弹这个,不是说是短信运营成本么?为啥不是第180天验证那次费用让我们付,而是每次授权都付? [图片] 手机号授权改造后的效果: 打开职位详情页:优先调用接口判断openId是否绑定过。 如果未绑定:使用button的open-type=“getPhoneNumber”,点击报名弹出手机号授权,授权成功后与openId进行绑定落库。 如果已绑定,页面通过变量判断使用wx.login静默授权,同时服务端拿到绑定的手机号后进行登录操作,同步返回登录态(token/jwtToken)。 退出登录页面增加解绑操作(服务端解除openId与手机号的绑定),此时用户再次点击报名,就会弹出手机号授权,方便用户切换手机号。 [视频]
2023-07-27 - ios下的ad组件穿透地图?
描述: 目前地图已支持view同层渲染, 在同层渲染的view里添加 ad 广告组件, view已经通过 catch:touchmove 阻止地图穿透。 但实际测试过程中,ios 机型, view不会引起地图拖动没错, 但是如果是滑动 ad 组件区域,地图仍旧可拖动。 [图片] 可复现的代码片段: https://developers.weixin.qq.com/s/PBGXmem47FBG
2022-08-03 - 插屏广告导致页面卡死,无法关闭
[视频] 有2个页面,第一个页面每次打开会调用插屏广告,第二个面不会调插屏广告。 复现流程:第一个页面打开,展示了插屏广告(有时候第一页广告不展示也可以复现)。关掉广告后,进入第二个页面。在第二个页面停留一定时间(满足再次打开第一个页面时会展示插屏广告),返回第一个页面,第一个页面弹出插屏广告。此时第一个页面卡死,插屏广告也无法关闭,只能杀掉小程序进程,才可以打开。 不会百分百的复现,安卓和ios都有可能出现。 也可能不是卡死,只是广告关不掉。点击插屏详情按钮,按钮有点击特效,但是页面没有变化。点击投诉是可以跳转的。点击关闭按钮,没有任何反应,点击黑色背景区域也无法关闭。小程序内的swiper是可以正常轮播的。
2021-10-08 - 蓝牙接口调用需要授权问题?
访问蓝牙、需要用户授权小程序处理用户的个人信息,需要获取用户明示同意,平台计划从2022年2月21日24时起对以下接口增加用户授权:访问蓝牙:调用wx.openBluetoothAdapter、wx.createBLEPeripheralServer,需要授权scope.bluetooth开发者可在平台调整前提前增加使用 wx.getSetting 获取用户当前的授权状态的逻辑,若授权状态为false可以调用 wx.openSetting 打开设置界面,引导用户开启授权。 openSetting 打开设置界面是还没有蓝牙选项 ??????????
2022-01-05 - 小程序wx.request存在大量失败请求(失败率为0.6%-2%),其中75%为请求超时?
目前小程序wx.request存在大量失败请求,失败率为0.6%-2% 其中75%为请求超时,但网关接口性能最大响应时间在400ms,官方能不能给分析一下? 急!!!
2019-11-21