前端监控系列-数据上报
字数 821 / 2 min 读完 / 阅读性能监控和错误上报只是辅助功能,不应阻塞页面加载,因此只有当页面完成加载后,我们才进行数据获取和上报(实际上,页面加载完成前也获取不到必要信息),性能数据可以在页面加载完之后上报,尽量不要对页面性能造成影响。
上报时机
使用window.requestIdleCallback()
,该方法将在浏览器的空闲时段内调用的函数排队。这使开发者能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应。
window.onload = () => {
if (window.requestIdleCallback) {
window.requestIdleCallback(() => {
monitor.performance = getPerformance()
monitor.resources = getResources()
})
} else {
setTimeout(() => {
monitor.performance = getPerformance()
monitor.resources = getResources()
}, 0)
}
}
当然,你也可以设一个定时器,循环上报。不过每次上报最好做一下对比去重再上报,避免同样的数据重复上报。
数据上报
对于一个埋点方案来说,数据上报有两个点需要着重考虑:
- 对跨域做特殊处理。
- 页面销毁后,如何还能够将未上传的埋点数据成功上报?
传统的XHR发送数据请求的方式,对上面提到的两个点都无能为力。在数据上报过程中,较为常用的有两种方式:
- 动态创建img标签,在 img.src 中拼接url的方式发送请求
- 调用 sendBeacon 接口发送数据
new img
利用img
标签的src
属性发送请求的方式,具体执行方案如下:
let _img = new Image();
_img.src = `${url}?${util.spliceParam(params)}`;
_img.onload = _img.onerror = function() {}
它非常契合埋点数据上报这个应用场景:
- 只上报的数据不需要接收响应;
- img的src属性天然地不存在跨域问题。
这种使用方式也存在缺陷。首先对于src 中的URL内容是有大小限制的,太大的数据量不适用。详细看这里。其次,在页面卸载的时候,若存在数据未发送的情况,会先将对应的数据发送完,再执行页面卸载。这种情况下,会在体验上给使用者带来不方便。
sendBeacon
sendBeacon方法是一个异步、非阻塞的数据传输方法。具体使用方式如下:
window.navigator.sendBeacon && window.navigator.sendBeacon(url, params)
它的特点是:
- Beacon请求是Post方式。
- Beacon请求优先避免与关键操作和更高优先级的网络请求竞争。
- Beacon请求可以有效地合并,以优化移动设备上的能量使用。
- Beacon保证页面卸载之前启动信标请求,并允许运行完成且不会阻塞请求或阻塞处理用户交互事件的任务。
- 返回值:sendBeacon 方法被执行后返回一个布尔值,
true
代表用户代理成功地将信标请求加入到队列中,否则返回false
。
对于sendBeacon方法,它的局限性体现在:
- 不能跨域,需要服务端设置。
- 新特性接口,兼容性存在问题。
因此,在实际的应用过程中,需要针对实际情况,结合 Img 标签 与 sendBeacon 的方式一起使用。
全文完。