最近项目在讨论数据上报,现有的做法是:web端每隔15s上报数据到后台。后端表示这样会被前端搞死的,如果同时在线几百万用户,后端会崩掉,一阵喧嚣的讨论后,关键点来到了:关闭浏览器或页面时如何保证数据成功发送到服务端。
其实数据上报包含两部分:
- 上报时机
- 上报请求
上报时机
在什么做数据上报呢?其实这个跟业务是息息相关的,比如你要想记录用户的行为轨迹,那么你就必须定时去记录用户的操作轨迹,然后在页面跳出时将这些数据上报到服务端。
以上是一个比较标准的做法,但如果用户页面停留时间长的话,行为轨迹的产生时间与数据统计时间会存在时延,存在一些不可抗拒的因素导致数据丢失:比如用户的机器crash了,停电了等等。
不过一般来说,我们会在页面卸载的时候发送统计数据。
有两个事件:
visibilitychange:在tab页切换、页面关闭、跳出、浏览器关闭时触发。pagehide:第二个会在页面关闭、跳出、浏览器关闭时触发
因此,第一个时页面卸载的时机。
上报数据
需要提到的是,页面卸载时进行数据上报不能使用普通的Ajax请求,因为浏览器会忽略或取消掉这类请求。所以我们采用navigator.sendBeaconAPI来上报数据。
这也是MDN推荐的做法。
window.addEventListener(
"pagehide",
(event) => {
navigator.sendBeacon("url" ,"some data here");
},
false
);
它会发送一个post请求到服务端。数据支持二进制、字符串等。基本能满足大部分场景了。
这种方式
兼容性
PC端
在最新版的chrome、safari、firefox上测试,关闭浏览器、关闭tab页面、跳出页面、前进、后退等都会触发pagehide事件,事件回调里发送的数据在服务端都可以正常收到的。
而visibilitychange除了在上述场景触发外,还会在页面可见性改变时触发。
手机端
主要测试了safari和chrome。测试发现pagehide里发出的请求无法被后端收到.而visibilitychange发送的请求可以被收到,但事件的触发时机有些许的差异:
对于safari:
- 页面切换tab,可以正常发出
- 页面随浏览器被切换到后台,可以正常发出
- 页面息屏,可以正常发出
- 页面随浏览器被关闭,可以正常发出
- 刷新页面,可以正常发出
- tab直接被关闭(无论页面是后台还是前台),无法发出。
对于chrome:
- 切换tab,可以正常发出
- 页面随浏览器被切换到后台,可以正常发出
- 页面息屏,可以正常发出
- 页面随浏览器被关闭,可以正常发出
- 通过下拉关闭tab页,不会发出。
总结就是,chrome切换tab页时,点击+或者标签按钮时当前页的可视性就发生改变了。
而safari则是点击标签按钮并点击目标页后,才触发当前页面的可视性改变。
总结
pc端可以考虑pagehide或visibilitychange,手机端则只能用visibilitychange
感谢阅读,如有任何疑惑或指教,不胜感激!