前端 如何检测到当前的网页已经退出_如何监控网页崩溃?
本文是如何监控网页的卡顿?的下篇。今天我们把话题聚焦在如何监控网页的崩溃上。寸志:如何监控网页的卡顿?zhuanlan.zhihu.com
崩溃和卡顿有何差别?
卡顿也就是网页暂时响应比较慢,JS 可能无法及时执行,这也是上篇网页卡顿监控所依赖的技术点。
但崩溃就不一样了,网页都崩溃了,页面看不见了,JS 都不运行了,还有什么办法可以监控网页的崩溃,并将网页崩溃上报呢?
但,天无绝人之路,方法总是有的。
load 与 beforeunload 事件
搜遍互联网,几乎找不到方法,最终碰上了这篇文章。本文利用 window 对象的 load 和 beforeunload 事件实现了网页崩溃的监控。http://jasonjl.me/blog/2015/06/21/taking-action-on-browser-crashes/jasonjl.me
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'));
}
一图胜千言:使用 load 和 beforeunload 事件实现崩溃监控
这个方案巧妙的利用了页面崩溃无法触发 beforeunload 事件来实现的。
在页面加载时(load 事件)在 sessionStorage记录 good_exit 状态为 pending,如果用户正常退出(beforeunload 事件)状态改为 true,如果 crash 了,状态依然为 pending,在用户第2次访问网页的时候(第2个load事件),查看 good_exit 的状态,如果仍然是 pending 就是可以断定上次访问网页崩溃了!
但这个方案有问题:采用 sessionStorage 存储状态,但通常网页崩溃/卡死后,用户会强制关闭网页或者索性重新打开浏览器,sessionStorage 存储但状态将不复存在;
如果将状态存储在 localStorage 甚至 Cookie 中,如果用户先后打开多个网页,但不关闭,good_exit 存储的一直都是 pending,完了,每有一次网页打开,就会有一个 crash 上报。全民直播 一开始采用的就是这个方案,发现就算页面做了优化,crash 不下降,与 PV 保持比例,才意识到这个方案的问题之处。
基于 Service Worker 的崩溃统计方案
随着 PWA 概念的流行,大家对 Service Worker 也逐渐熟悉起来。基于以下原因,我们可以使用 Service Worker 来实现网页崩溃的监控:Service Worker 有自己独立的工作线程,与网页区分开,网页崩溃了,Service Worker 一般情况下不会崩溃;
Service Worker 生命周期一般要比网页还要长,可以用来监控网页的状态;
网页可以通过 navigator.serviceWorker.controller.postMessage API 向掌管自己的 SW 发送消息。
基于以上几点,我们可以实现一种基于心跳检测的监控方案:
p1:网页加载后,通过 postMessage API 每 5s 给 sw 发送一个心跳,表示自己的在线,sw 将在线的网页登记下来,更新登记时间;
p2:网页在 beforeunload 时,通过 postMessage API 告知自己已经正常关闭,sw 将登记的网页清除;
p3:如果网页在运行的过程中 crash 了,sw 中的 running 状态将不会被清除,更新时间停留在奔溃前的最后一次心跳;
sw:Service Worker 每 10s 查看一遍登记中的网页,发现登记时间已经超出了一定时间(比如 15s)即可判定该网页 crash 了。
一些简化后的检测代码,给大家作为参考:
// 页面 JavaScript 代码if (navigator.serviceWorker.controller !== null) {
let HEARTBEAT_INTERVAL = 5 * 1000; // 每五秒发一次心跳 let sessionId = uuid();
let heartbeat = function () {
navigator.serviceWorker.controller.postMessage({
type: 'heartbeat',
id: sessionId,
data: {} // 附加信息,如果页面 crash,上报的附加数据 });
}
window.addEventListener("beforeunload", function() {
navigator.serviceWorker.controller.postMessage({
type: 'unload',
id: sessionId
});
});
setInterval(heartbeat, HEARTBEAT_INTERVAL);
heartbeat();
}sessionId本次页面会话的唯一 id;
postMessage 附带一些信息,用于上报 crash 需要的数据,比如当前页面的地址等等。
const CHECK_CRASH_INTERVAL = 10 * 1000; // 每 10s 检查一次const CRASH_THRESHOLD = 15 * 1000; // 15s 超过15s没有心跳则认为已经 crashconst pages = {}
let timer
function checkCrash() {
const now = Date.now()
for (var id in pages) {
let page = pages[id]
if ((now - page.t) > CRASH_THRESHOLD) {
// 上报 crash delete pages[id]
}
}
if (Object.keys(pages).length == 0) {
clearInterval(timer)
timer = null
}
}
worker.addEventListener('message', (e) => {
const data = e.data;
if (data.type === 'heartbeat') {
pages[data.id] = {
t: Date.now()
}
if (!timer) {
timer = setInterval(function () {
checkCrash()
}, CHECK_CRASH_INTERVAL)
}
} else if (data.type === 'unload') {
delete pages[data.id]
}
})
都挺简单的代码,不细说了。
方案的可行性
兼容性:
Service Worker 的普及率已经相当高了,鉴于国内各种浏览器都是 Chrome 内核,而且版本已经在 Chrome 45 以上,已经覆盖了相当一部分用户。作为监控,数据覆盖大部分就好。Service Worker 兼容性
可靠性:
这应该是我目前已知可以相对准确判断出网页崩溃的方式了。不过我们的方案还在测试环境,上线一段时间后再给大家共享数据。
对浏览器厂商的建议
题图的 Crash 列表,可以在 Chrome 中访问 chrome://crashes/ 看到,如果厂商可以提供一个 API,在页面打开时,可以获知用户上一次崩溃的信息就很棒了!
前端 如何检测到当前的网页已经退出_如何监控网页崩溃?相关推荐
- web前端网页设计作业_如何学习网页前端设计培训?
学习网页的前端设计分为几个步骤或者说几个网页设计教程大类. 一个是熟练掌握各种网页设计需要的操作软件,然后就是WEB界面设计与项目设计,最后还有WEB整站设计实训. 如何学习网页的前端设计呢? 许多零 ...
- 挂代理无法访问网页了怎么办_微信H5网页授权
1 第一步:用户同意授权,获取code2 第二步:通过code换取网页授权access_token3 第三步:拉取用户信息(需scope为 snsapi_userinfo)SpringBoot:2.1 ...
- hbuilder怎么设置网页的大小_大明:网页字体大小怎么调?教你方法一键搞定
大家好,我是大明,网页的字体太大或太小都影响我们正常的浏览,导致网页字体大小不合适的主要原因是"显示适配器分辨率","显卡驱动问题","网页字体设置不 ...
- 网页突然乱码_电脑打开网页出现乱码
请不要盗用我的答案!! 一号方案[新P] 注意[原创]: 1.安全模式下,效果更好! 2. 以下所要使用的软件,都要安装或升级到最新版本,以保证使用的效果. 3. 不杀毒,直接使用以下方法也可以 .若 ...
- python制作网页难吗_怎么做网页制作(用python做网页与html)
想要做一个大型的网站,必须拥有较强的网站设计能力,而且photoshop.flash.Cool 3d.Gif Animator等网页制作的辅助工具必须都懂,数据库是网站的强大支持,因此,数据也需要懂. ...
- python阿里巴巴排名_全自动监控网页关键词排名(Python实现)
在运行之前,先要把关键词按行分隔,保存成txt文件,并在运行参数中让脚本去读取它.每次运行之后,会在/home/rank/文件夹下,创建一个类似1970-01-01.csv这样文件名的文件,保存着当日 ...
- div+css静态网页设计游戏网站设计——仿君海游戏官网(13页) HTML+CSS大作业_ 手游网页制作作业_网游网页设计...
HTML5期末大作业 文章目录 HTML5期末大作业 一.作品展示 二.文件目录 三.代码实现 四.获取更多源码 一.作品展示 二.文件目录 三.代码实现 <!DOCTYPE html> ...
- HTML+CSS大作业_ 美食网页制作作业_生猛海鲜美食网页设计
- HTML+CSS大作业: 美食网页制作作业_生猛海鲜美食网页设计
- 【文件上传漏洞-03】前端JS检测与绕过实例—以upload-labs-1为例
目录 1 前端JS检测与绕过 2 前端JS检测与绕过实例 2.1 实验目的 2.2 操作环境 2.3 前期准备 2.4 具体过程 2.4.1 文件上传前期盲测 2.4.2 方法一:删除JS直接上传 2 ...
最新文章
- 那些年php编程犯过的错(1) -- 字符串相等
- java 内存映射文件进程间通讯_[转]Windows环境下利用“共享内存”实现进程间通信的C/C++代码---利用CreateFileMapping和MapViewOfFile...
- boost::hana::monadic_fold_right用法的测试程序
- 使用wireshark+ssh+tcpdump远程抓包
- 矩阵运算——平移,旋转,缩放
- python魔法函数和装饰器_python魔法方法、构造函数、序列与映射、迭代器、生成器...
- db2 sql 判断select是否为空_学会复杂一点的SQL语句:Oracle DDL和DML
- c++代码转为go_C++调用Go方法的字符串传递问题及解决方案
- awesome python 中文版 相见恨晚!(pythonNB的第三方资源库)
- 小甲鱼python课后题简书_Python 练习题汇总
- python类和对象_Python类和对象
- 【L2TP】L2TP IPsec设置
- FXTM富拓:美数据亮眼,美元这是要涨了?
- [46]python画出心形图
- java二重积分_《University Calculus》-chaper13-多重积分-二重积分的引入
- python-pptx----母版制作
- ARM程序的镜像文件以及在内存中的分区
- 【win10】开始菜单输cmd、运行、控制面板后点击无反应,win+x无反应,开始菜单右键无反应
- TFS2010 创建项目时提示“未能解析远程主机”的解决办法
- 免疫组库vdj的数据处理(TCR/BCR)