首页 > 编程语言 >#yyds干货盘点#JavaScript 网页异常捕获

#yyds干货盘点#JavaScript 网页异常捕获

时间:2022-12-03 17:31:14浏览次数:48  
标签:function yyds console onerror 捕获 JavaScript 干货 error catch

一、异常大概分类

一般我们想要捕获的异常大概分类:

  • 语法错误
  • onerror 事件代码块与​​语法错误代码块​​不在一起,例如trycatche
  • 或者同在一个代码块,但是​​语法错误代码块​​异步执行 以上情况都可以用onerror捕获语法错误
setTimeout(() => { 
eval('function()')
}, 1000);
// Uncaught SyntaxError: Function statements require a function name
  • 引用错误,类型错误,uri 错误,范围错误等等
    非try catch包裹情况下,可以使用 one rror 捕获同步错误、异步错误
console.log(a) // Uncaught ReferenceError: a is not defined 
Array.test() // 调用了 Array 上不存在的 test,值为 undefined,作为函数执行,则会抛出类型错误 // Uncaught TypeError: Array.test is not a function
new Array(12221312312) // Uncaught RangeError: Invalid array length
decodeURI('%') // Uncaught URIError: URI malformed
  • try{} catch{}

若 try 代码块报错,只能在 catch 中捕获。但是 try 代码块中若有异步错误代码,catch 无法捕获,会被 one rror 捕获

try { 
setTimeout(() => {
console.log('a', a) // 可以被 one rror 捕获
}, 1000) }
catch(e) { console.log('e', e) } // Uncaught ReferenceError: a is not defined

Promise 抛出错误

  • 没有设置 catch 捕获
let p = new Promise((resolve, reject) => { 
reject(1) }
) // 这里没有做 catch 处理
// Uncaught (in promise) 1
复制代码
  • 在 catch 中报错没有捕获
;(async function xx() { 
try { throw 1 }
catch(e) {
console.log('a', a) // 这里出错可以使用 unhandledrejection 来捕获
}
})()
// Uncaught ReferenceError: a is not defined
  • 上面两种情况可以监听 unhandledrejection 捕获错误
window.addEventListener('unhandledrejection', function(e) { 
// e.preventDefault(); // 阻止异常向上抛出
console.log('捕获到异常 unhandledrejection :', e)
})
  • 静态资源加载失败
  • 在资源上添加 one rror 事件
// html 
// <img src="" alt="" id="imgID">
// js
let imgID = document.getElementById('imgID')
imgID.onerror = function(e) {
console.log('img load error :>> ', e);
} // 注意:onerror 需要定义之后,再设置图片路径,才能捕获到加载失败
imgID.src = 'http://xxx.png'
  • 静态资源网络请求失败事件不会冒泡,需要在捕获阶段捕获chrome、FF 中可以通过冒泡方式监听 error 事件捕获资源加载失败
// 注意:此处会与上面的 one rror 事件一起触发,将导致日志重复上报
// 可以只使用 addEventListener 捕获模式统一监听, 就不需要注册 window.onerror 了
window.addEventListener(
'error',
error => {
console.log('addEventListener 捕获到异常:', error)
},
true
)
  • 网页崩溃
  • 网页加载后,埋入一个标志,表示正在加载
// 初次进来,将埋入一个标志,值为 pending ,正常退出后,会设置为 true 
// 若网页崩溃,第二次回来页面后,读取当前标志,如果值存在且为 true 则表示正常退出
// 如果不是 true ,则表示上次可能是崩溃了,需要上报之前定时更新的时间值
if(localStorage.getItem('good_exit') && localStorage.getItem('good_exit') !== 'true') {
localStorage.getItem('time_before_crash') // 日志上报,将崩溃之前的时间一起上报
}
window.addEventListener('load', function () {
localStorage.setItem('good_exit', 'pending'); // 定时更新崩溃之前的网页时间
setInterval(function () {
localStorage.setItem('time_before_crash', new Date().toString());
}, 10000);
})
window.addEventListener('beforeunload',
function () { // 网页正常退出后,将埋入标志,设置成 true,表示正常退出
localStorage.setItem('good_exit', 'true');
})

上面是在 ​​第二次​​ 进入页面才知道网页崩溃,那么有什么方法可以在网页崩溃之后就可以上报呢

  • 可以使用 Service Worker 来进行监控 其生命周期与页面无关(关联页面未关闭时,它也可以退出,没有关联页面时,它也可以启动)
1、注册 service worker js 
2、 每间隔 10 秒,就向 worker 发送消息 消息中包含:
{
type 字段:active 表示正常活跃,exit 表示正常退出
time 字段:表示当前时间
}
在页面要退出后,发送 type: exit,表示正常退出
3、 worker 内部注册有消息接收事件,接收页面发送过来的消息
接收到 type 为 active,表示正常活跃,更新内部 time 的值
接收到 type 为 exit,表示正常退出,更新内部 time 值为 0
worker 内部维护一个状态对象,包含时间,值为页面发送过来
每隔 15 秒检查一次,若时间与上一次没有改变,则说明页面可能崩溃(注意区分 time 为 0 的情况)
  • Script Error
  • 跨域脚的错误信息,因为处于保护信息的原因,只会展示 Script Error, 通过以下方式解决
1、外链添 crossorigin 属性:<script crossorigin src="http://other-domain.js"></script> 
2、同时的 Access-Control-Allow-Origin: 设置为 * 或者 当前域名
  • iframe Error
<iframe src="./test.html"></iframe>
<script> window.frames[0].onerror = function(msg, source, lineno, colno,error) {
console.log('frames one rror :>> ', msg,source,lineno,colno,error)
} </script>
  • vue 自身 try catch 处理了错误,导致我们无法捕获
    使用 Vue 提供的 errorHandler 方法捕获
Vue.config.errorHandler = function(err, vm, info) { 
let {
message, // 异常信息
name, // 异常名称
script, // 异常url
line, // 异常行号
column, // 异常列号
stack // 异常堆栈信息 } = err
// vm 为抛出异常的 Vue 实例
// info 为 Vue 特定的错误信息,比如错误所在的生命周期钩子
console.log('vue err,vm,info :>> ', err, vm, info)
}

所以捕获错误总结下来:

// 1、try catch 中的 catch 错误捕获 
可以在 webpack 打包时候,使用 AST 方式解析并在 catch 中插入日志上报代码
// 2、error 事件
window.addEventListener( 'error', error => {
let data = {} // 此处与上面的 one rror 会重复事件
let { colno, lineno, message, filename, error, stack } = error //不一定所有浏览器都支持 colno 参数
let col = colno || (window.event && window.event.errorCharacter) || 0
data.url = url
data.line = line
data.col = col
if (!!stack){
//如果浏览器有堆栈信息
//直接使用
data.msg = stack.toString()
}else if (!!arguments.callee){
//尝试通过callee拿堆栈信息
let ext = []
let f = arguments.callee.caller, c = 3 //这里只拿三层堆栈信息
while (f && (--c>0)) {
ext.push(f.toString())
if (f === f.caller) {
break //如果有环
}
f = f.caller
}
ext = ext.join(",") data.msg = ext
}
console.log('3、addEventListener error 捕获阶段>>>异常:', data)
}, true )
// 3、unhandledrejection
window.addEventListener('unhandledrejection', function(e) {
// e.preventDefault();
// 阻止异常向上抛出
console.log('4、promise 异常 unhandledrejection :', e)
})
// 4、errorHandler
Vue.config.errorHandler = function(err, vm, info) {
// vm 为抛出异常的 Vue 实例
// info 为 Vue 特定的错误信息,比如错误所在的生命周期钩子
let {
message, // 异常信息
name, // 异常名称
script, // 异常url
line, // 异常行号
column, // 异常列号
stack // 异常堆栈信息
} = err
console.log('2、vue errorHandler :>> ', err, vm, info) }

标签:function,yyds,console,onerror,捕获,JavaScript,干货,error,catch
From: https://blog.51cto.com/u_11365839/5908607

相关文章

  • 读《你不知道的JavaScript》
    读《你不知道的JavaScript》Part1作用域与闭包词法作用域定义在词法阶段的作用域。换句话说,词法作用域就是由你在写代码时将变量和块作用域写在哪里来决定的。词......
  • Javascript随机排列数组-要求概率一样
    今天做了一道很有意思的题。如何在Js中实现一个随机排列数组的算法,要求排列之后每一次组合出现的概率相同。完整题目如下:etarr=[1,2,3];shuffle(arr);//arr=[3......
  • JavaScript入门④-万物皆对象:Object
    01、Object对象Object是JavaScript的一种数据类型,它用于存储各种键值集合和更复杂的实体,是一组数据和功能的集合。JS中几乎所有对象都是继承自Object,Array、RegExp、......
  • #yyds干货盘点#git常用命令
    git的基本功工作方式包括以下几个:主分支:master开发分支:develop提测分支:relase如:relase/V2.0.0新功能开发,develop分支检出一个feature分支开发(合并后可删除)bug修复......
  • #yyds干货盘点#【愚公系列】2022年12月 微信小程序-项目篇(公交查询)-02周边站点-获取
    前言1.相关API逆地址解析:提供由经纬度到文字地址及相关位置信息的转换能力,广泛应用于物流、出行、O2O、社交等场景。服务响应速度快、稳定,支撑亿级调用。可以满足以下相......
  • #yyds干货盘点# LeetCode程序员面试金典:字符串压缩
    题目:字符串压缩。利用字符重复出现的次数,编写一种方法,实现基本的字符串压缩功能。比如,字符串aabcccccaaa会变为a2b1c5a3。若“压缩”后的字符串没有变短,则返回原先的字符串......
  • 【干货】超详细!TPC7062封装MQTT协议教程
    【干货】超详细!TPC7062封装MQTT协议教程一.功能简介通过将报文分解为16进制格式的字符串(比如:101C00044D51545404C2),再通过TPC-7062进行组包,利用串口服务器的TCP/IP协议栈连接......
  • #yyds干货盘点# 名企真题专题:
    1.简述:描述22娘和33娘接到了小电视君的扭蛋任务:一共有两台扭蛋机,编号分别为扭蛋机2号和扭蛋机3号,22娘使用扭蛋机2号,33娘使用扭蛋机3号。扭蛋机都不需要投币,但有一项特殊能力......
  • Web入门:JavaScript搜索展开
    欢迎来的我的小院,恭喜你今天又要涨知识了!案例内容利用JavaScript实现搜索框的移动展开。演示学习<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF......
  • javascript: jquery-confirm.js
     <!doctypehtml><html><head><metacharset="utf-8"><metaname="viewport"content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.......