上报方式
我们采集了埋点数据后, 就需要把采集的数据交给后端。
那么我们应该如何上报?
我们得考虑接口跨域、上报异常(正在进行上报时, 用户关闭了页面, 这样上报就会失败)、性能要求(不能应用应用使用)
基于以上要求, 提供了三种方式供用户自行选择
sendBeacon
浏览器引入的 sendBeacon 方法,发出的是异步请求,但是请求是作为浏览器任务执行的,
与当前页面是脱钩的。因此该方法不会阻塞页面卸载流程和延迟后面页面的加载,用户体验较好。
缺点: 浏览器存在支持问题
img
避免跨域
1x1 像素 img 对网页内容的影响几乎没有影响
图片请求不占用 Ajax 请求限额
不会阻塞页面加载,影响用户的体验
相比 XMLHttpRequest 对象发送 GET 请求,性能上更好
触发 GET 请求之后不需要获取和处理数据、服务器也不需要发送数据
post
超出 get 最大请求数、或者用户手动进行上报方式配置则会采用 post
默认情况下优先级 sendBeacon > img > post
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| const urlIsLong = (url: string) => { let totalLength = 0, charCode = 0; for (var i = 0; i < url.length; i++) { charCode = url.charCodeAt(i); if (charCode < 0x007f) { totalLength++; } else if (0x0080 <= charCode && charCode <= 0x07ff) { totalLength += 2; } else if (0x0800 <= charCode && charCode <= 0xffff) { totalLength += 3; } } return totalLength < 2000 ? false : true; };
if (navigator.sendBeacon) { sendBeacon(url, params); } else if (method === "POST" || urlIsLong(str)) { xmlRequest(url, params); } else { const img = new Image(); img.src = `${url}?${str}`; }
|
上报拦截
用户可能需要在上传前对参数进行变更, 我们可以在上报前提供拦截器给用户进行变更参数操作。
这里借鉴Axios Interceptor拦截器实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| class Interceptor { private handlers; constructor() { this.handlers = []; }
use(fulfilled, rejected, options) { this.handlers.push({ fulfilled, rejected }); } ... }
export default Interceptor;
class SimpleJsTracker { constructor(options: IDefaultOptions) { this['_init'](options); this['interceptors'] = { sendTracker: new Interceptor() } } ... }
SJTracker.prototype.sendTracker = function (data = {}) { let reportData = Object.assign(Object.assign({}, this._options), data); this.interceptors.sendTracker.handlers.forEach((interceptor) => { const onFulfilled = interceptor.fulfilled; reportData = onFulfilled(reportData); }); sendTracker(this._options, reportData); };
|
文中完整代码
github > npm