背景
发现掘金请求中有一些请求类型是ping(目前只有比较新的chrome版本能看到),好奇是这种ping类型请求是使用什么发出来的。
image查MDN文档发现ResourceType其实有记录这种类型:
image也就是说ping类型其实有2种:
- a标签ping属性
- 浏览器Beacon
掘金的ping类型请求属于第二种,本文主要介绍第二种。
点击请求list的Initiator查看具体发起该请求的代码:
image格式化代码后,代码如下:
image可以看到是用了navigator.sendBeacon() 方法。
navigator.sendBeacon()
navigator.sendBeacon()
方法可用于通过HTTP将少量数据异步传输到Web服务器。
navigator.sendBeacon(url, data)接受两个参数:
-
url,请求的地址
-
data,请求的数据, 可以是
ArrayBufferView
或Blob
,DOMString
或者FormData
类型的数据。
📢:该请求是post请求,成功返回true,失败返回false。
相对于xhr发送的请求有什么优点
sendBeacon()
的适用场景是埋点,用户行为分析等,特别是对于需要在页面卸载时发送的埋点。
如果使用xhr要在页面卸载时发送埋点需要怎么做?
常见的方案是在 unload 事件处理器中发起一个同步请求来发送数据,但是这种做法会导致页面卸载被延时。
为什么不用异步请求呢?
异步请求,很可能在它即将发送的时候,页面已经卸载了,从而导致请求被canceled或者发送失败。
而用sendBeacon()
发送请求可以保证不拖延页面卸载并且请求也能发送出去。
为什么页面卸载也能正常发送请求
这不得不提到fetch,fetch选项有一个keepalive的配置。
imagekeepalive用于页面卸载时,告诉浏览器在后台保持连接,继续发送数据。而sendBeacon() 底层就是使用fetch。
sendBeacon传输不止有传输长度的限制(约65536个字符),数据大小的限制64kb,这些都是浏览器层面的限制,不同的浏览器可能还存在细微的差别。https://stackoverflow.com/questions/28989640/navigator-sendbeacon-data-size-limits
兼容性
除了IE之外的绝大多数浏览器都开始支持了。
image总结
如果浏览器支持navigator.sendBeacon()
,推荐使用如下写法:
// ......data是需要上报的数据
if(navigator.sendBeacon) {
const status = navigator.sendBeacon('domain.com/api/postData',
JSON.stringify(data));
} else {
// 使用向下兼容的方式
}
相关文档
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/ResourceType
https://developer.mozilla.org/zh-CN/docs/Web/API/Navigator/sendBeacon
https://stackoverflow.com/questions/28989640/navigator-sendbeacon-data-size-limits
网友评论