前端小玩具~错误捕获定位工具(promise 错误捕获)
wxin55 2024-10-25 18:06 11 浏览 0 评论
正文
我们在平时的工作中,开发功能的同时不可能把场景考虑的面面俱到,而生产环境往往情况是非常复杂的,用户录入进去的数据总是千奇百怪,那如果遇到问题的话,我们又要如何进行排查呢?总不可能让用户录个屏吧哈哈~所以我们就出现了前端埋点的操作,不过埋点的方向以及文章都挺多的,也都挺复杂的,这篇文章我们就讲一个比较有趣的错误捕获思路。
我们平时在使用框架开发遇到bug时,比如Vue,如果是在本地环境,我们在控制台可以很容易的找到出现问题的文件,甚至点击进入即可直接定位到我们的文件中对应报错的位置,这样排查问题就比较方便。而在生产环境,我们可以配置sourcemap,就也能比较方便的定位到问题出现的地方。但这样的话就会出现一个问题,首先上传到服务器的包体积就会因为生成了很多map文件而变得很大,其次我们的网站代码会非常容易暴露甚至是直接被调试,而且这样子也仅仅是我们自测的时候去发现问题,无法监测到用户端到底是做了什么操作才出现的问题。
那么,有没有一个方法是可以监控到客户端用户操作时,出现问题的代码位置呢?
思考:
综上,我们这次要做的这个工具的目的就比较明确了:
- 错误捕获
- 错误分析/错误定位
- 错误收集/日志输出
前置
在错误捕获之前,我们先提前了解一个服务端的库——source-map
使用source-map库,我们可以通过向该库暴露出的方法中传入bug出现的文件对应的map文件,以及错误的行数和列数,通过对应的方法解析后,我们可以得到该错误出现的源文件以及具体在源文件中的定位。
至此,我们明确了错误捕获中,我们主要就是想拿四个信息:
- 错误的message信息
- 错误出现的文件名
- 错误行数
- 错误列数
那么,我们可不可以设计这样一个流程呢?
- 1.在配置文件中将sourcemap的配置打开,从而使得项目打包后会生成map文件。
- 2.通过编写webpack插件,监听webpack打包完成钩子,在打包完成后触发,将生成的map文件自动上传到我们的服务器上。
- 3.然后在前端,通过错误捕获,将报错信息传给我们的服务器,由服务器根据报错信息再结合map文件,最终解析出我们的报错行数,同时形成日志输出出来并记录下来。
这样的话,我们就可以非常方便的捕获错误,监控生产问题,同时也实现了一个简单的webpack插件(又可以拿去和面试官吹水了~)。
错误捕获
onerror
前端的错误捕获我们最常见的当然是window.onerror了,我们可以通过定义window.onerror函数来对全局错误进行捕获。
通过window.onerror我们很容易可以拿到我们想要的具体信息。
errorHandler
但window.onerror并不能捕获到框架组件生命周期的错误,所以我们可以再补充一个框架的错误捕获,以Vue为例:
我们在errorHandler事件中,可以拿到错误对象err,vue实例,错误信息。这里我们并不能像上面onerror错误捕获一样很方便的取出出错的行数和列数,但我们能够拿到一个完整的错误堆栈对象,那么我们就可以对错误对象的堆栈信息进行处理,提取出我们想要的行数和列数。
这里用到了一个堆栈解析工具——StackTrace-Parser
补充
错误捕获还有一个onunhandledrejection的事件,用于捕获Promise类型的错误,但是经过尝试发现不是很好去拿到错误的定位信息,同时,考虑到一般Promise我们会使用catch去处理异常的操作,所以这里就暂时不处理这个类型的错误事件了。
至此,我们的捕获相关的逻辑已经完成,剩下的就是如何设计服务端,如何将这些信息传递给服务端并完成解析了。
错误分析/错误定位
服务端,我们设计两个接口,一个用于上传map文件(upload),一个用于接收错误信息(sendErrorLog)。
上传接口就不多说了,主要就是在前端打包完成之后,服务端接收传过来的map文件。我们主要看一下接收错误信息的接口逻辑。
整体的思路就是:
- 服务器启动时读取upload文件夹下的所有map文件,将对应文件的内容读取出来
- 在sendErrorLog接口被调用后,通过source-map库去解析错误信息
- 输出错误日志
这里考虑到一般服务器我们都是一直启动的状态,所以在调用解析逻辑之前,先判断souceMap数据是否已经读取出来,如果没有读取出来,再同步去读取,之后再去解析错误信息。
完善前端逻辑
接口已经有了,这里我们再回过头完善一下前端的逻辑。
首先,我们根据前面对错误捕获的了解,完成一下错误上传的逻辑,:
然后,我们开始实现map文件上传的逻辑。
我们先去找一个webpack打包完成输出文件后的钩子——afterEmit。
在这个钩子触发时,说明打包文件已经被输出出来了,我们可以去读取打包文件的js文件夹,从中过滤出map文件,上传至服务器,同时在打包文件中将map文件进行删除操作。
测试效果
逻辑写完了,我们在前端代码中留下一些bug来测试一下效果。
然后,我们执行npm run build打包操作。
可以看到我们打包完成后的dist文件夹中,已经没有了map文件:
而在服务端,我们接收到了这些map文件。
上传map文件逻辑没有问题,接下来,我们看一下错误解析逻辑。
我们可以在本地安装一个serve包,便于我们快捷的以dist文件夹为基础起一个小型服务器。
将dist文件夹在终端中打开,执行执行serve -p 8080。
点击按钮触发bug,我们可以看到错误已被成功捕获,并将对应的信息通过接口传递给服务端。
在服务端的输出中,我们可以看到已对错误进行了解析,错误发生的定位信息已经输出出来了,对照前端文件中错误发生的位置也是没有问题的~
原文链接:https://juejin.cn/post/7422145784799330358
相关推荐
- ES6中 Promise的使用场景?(es6promise用法例子)
-
一、介绍Promise,译为承诺,是异步编程的一种解决方案,比传统的解决方案(回调函数)更加合理和更加强大在以往我们如果处理多层异步操作,我们往往会像下面那样编写我们的代码doSomething(f...
- JavaScript 对 Promise 并发的处理方法
-
Promise对象代表一个未来的值,它有三种状态:pending待定,这是Promise的初始状态,它可能成功,也可能失败,前途未卜fulfilled已完成,这是一种成功的状态,此时可以获取...
- Promise的九大方法(promise的实例方法)
-
1、promise.resolv静态方法Promise.resolve(value)可以认为是newPromise方法的语法糖,比如Promise.resolve(42)可以认为是以下代码的语...
- 360前端一面~面试题解析(360前端开发面试题)
-
1.组件库按需加载怎么做的,具体打包配了什么-按需加载实现:借助打包工具(如Webpack的require.context或ES模块动态导入),在使用组件时才引入对应的代码。例如在V...
- 前端面试-Promise 的 finally 怎么实现的?如何在工作中使用?
-
Promise的finally方法是一个非常有用的工具,它无论Promise是成功(fulfilled)还是失败(rejected)都会执行,且不改变Promise的最终结果。它的实现原...
- 最简单手写Promise,30行代码理解Promise核心原理和发布订阅模式
-
看了全网手写Promise的,大部分对于新手还是比较难理解的,其中几个比较难的点:状态还未改变时通过发布订阅模式去收集事件实例化的时候通过调用构造函数里传出来的方法去修改类里面的状态,这个叫Re...
- 前端分享-Promise可以中途取消啦(promise可以取消吗)
-
传统Promise就像一台需要手动组装的设备,每次使用都要重新接线。而Promise.withResolvers的出现,相当于给开发者发了一个智能遥控器,可以随时随地控制异步操作。它解决了三大...
- 手写 Promise(手写输入法 中文)
-
前言都2020年了,Promise大家肯定都在用了,但是估计很多人对其原理还是一知半解,今天就让我们一起实现一个符合PromiseA+规范的Promise。附PromiseA+规范地址...
- 什么是 Promise.allSettled()!新手老手都要会?
-
Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的pr...
- 前端面试-关于Promise解析与高频面试题示范
-
Promise是啥,直接上图:Promise就是处理异步函数的API,它可以包裹一个异步函数,在异步函数完成时抛出完成状态,让代码结束远古时无限回掉的窘境。配合async/await语法糖,可...
- 宇宙厂:为什么前端离不开 Promise.withResolvers() ?
-
大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发。1.为什么需要Promise.with...
- Promise 新增了一个超实用的 API!
-
在JavaScript的世界里,Promise一直是处理异步操作的神器。而现在,随着ES2025的发布,Promise又迎来了一个超实用的新成员——Promise.try()!这个新方法简...
- 一次搞懂 Promise 异步处理(promise 异步顺序执行)
-
PromisePromise就像这个词的表面意识一样,表示一种承诺、许诺,会在后面给出一个结果,成功或者失败。现在已经成为了主流的异步编程的操作方式,写进了标准里面。状态Promise有且仅有...
- Promise 核心机制详解(promise机制的实现原理)
-
一、Promise的核心状态机Promise本质上是一个状态机,其行为由内部状态严格管控。每个Promise实例在创建时处于Pending(等待)状态,此时异步操作尚未完成。当异步操作成功...
- javascript——Promise(js实现promise)
-
1.PromiseES6开始支持,Promise对象用于一个异步操作的最终完成(包括成功和失败)及结果值的表示。简单说就是处理异步请求的。之所以叫Promise,就是我承诺,如果成功则怎么处理,失败怎...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- ES6中 Promise的使用场景?(es6promise用法例子)
- JavaScript 对 Promise 并发的处理方法
- Promise的九大方法(promise的实例方法)
- 360前端一面~面试题解析(360前端开发面试题)
- 前端面试-Promise 的 finally 怎么实现的?如何在工作中使用?
- 最简单手写Promise,30行代码理解Promise核心原理和发布订阅模式
- 前端分享-Promise可以中途取消啦(promise可以取消吗)
- 手写 Promise(手写输入法 中文)
- 什么是 Promise.allSettled()!新手老手都要会?
- 前端面试-关于Promise解析与高频面试题示范
- 标签列表
-
- hive行转列函数 (63)
- sourcemap文件是什么 (54)
- display none 隐藏后怎么显示 (56)
- 共享锁和排他锁的区别 (51)
- httpservletrequest 获取参数 (64)
- jstl包 (64)
- qsharedmemory (50)
- watch computed (53)
- java中switch (68)
- date.now (55)
- git-bash (56)
- 盒子垂直居中 (68)
- npm是什么命令 (62)
- python中+=代表什么 (70)
- fsimage (51)
- nginx break (61)
- mysql分区表的优缺点 (53)
- centos7切换到图形界面 (55)
- 前端深拷贝 (62)
- kmp模式匹配算法 (57)
- jsjson字符串转json对象 (53)
- jdbc connection (61)
- javascript字符串转换为数字 (54)
- mybatis 使用 (73)
- 安装mysql数据库 (55)