sendBeacon

简介

为了时常将用户行为或性能数据上报到服务器,且不影响用户体验,开发者通常会在页面卸载时进行数据上报

然而,传统的数据上报方式,如XMLHttpRequest或Fetch API,容易被页面卸载过程阻塞,导致数据丢失

navigator.sendBeacon API能解决这个问题,它可以在页面卸载时安全、可靠地发送数据

sendBeacon VS Ajax & Fetch

优点

  • 不受页面卸载过程的影响,确保数据可靠发送
  • 异步执行,不阻塞页面关闭或跳转
  • 能发送跨域请求

缺点

  • Fetch和Ajax都可以发送任意请求,而sendBeacon只能发送POST
  • Fetch和Ajax可以传输任意字节数据,而sendBeacon只能传送少量数据(64KB内)
  • Fetch和Ajax可以定义任意请求头,而sendBeacon无法自定义请求头
  • sendBeacon只能传输 ArrayBuffer、ArrayBufferView、Blob、DOMString、FormData或 URLSearchParams类型的数据
  • 若是处于危险的网络环境,或开启了广告屏蔽插件,此请求将无效

应用场景

  • 发送心跳包:将sendBeacon用于发送心跳包,以保持与服务器的长连接,避免长时间没有网络请求导致的连接关闭
  • 埋点:将sendBeacon用于在页面关闭或卸载时记录用户在线时间,PV、UV、错误日志上报、按钮点击次数
  • 发送用户反馈:将sendBeacon用于发送用户反馈信息,如用户意见、bug报告等,以便进行产品优化和改进

ping请求

ping请求是HTML5新增的、sendBeacon特有的请求类型

ping请求只能携带少量数据,不需要等待服务端响应,因此非常适合做埋点统计、日志统计等相关功能

使用

后端:

1
2
3
4
5
6
7
// sendBeacon只能接收post请求
app.post('/api/b', (req, res)=> {
console.log(req.body)
// sendBeacon不需要等待服务端的返回
// 所以返回简单内容即可,保持轻量级
res.send('ok')
})

前端:

1
2
3
4
5
6
7
8
const send = document.getElementById("send")
// 如果非要传一个JSON对象,这样传
const json = JSON.stringify({name:"yajue",age:24})
// 把json字符串转成blob
const blob = new Blob([json],{type:'application/json'})
send.addEventListener('click', ()=> {
navigator.sendBeacon('http://localhost:3000/api/b', blob)
})

具体应用方式