navigator.sendBeacon 是浏览器的 API,用于在浏览器后台发送异步请求,它不会等服务端响应。
它可以用于在页面卸载或关闭的时候,发送数据,以及在不阻塞页面卸载的情况下发送数据。
使用 navigator.sendBeacon
方法发送的请求是异步的,不会阻塞页面的卸载或关闭过程。
这对于需要在用户离开页面之前发送数据的情况非常有用。
优点
- 不受页面卸载过程的影响,确保数据可靠发送。
- 普通的
http
请求如XMLHttpRequest
和Fetch
在页面关闭或者刷新、前进、后退等操作时 , 这些请求有可能在页面销毁之前没有完成,导致数据丢失。 navigator.sendBeacon
的优先级是较低的,XMLHttpRequest
和fetch
这些同步请求,以及其他高优先级任务在它之前,navigator.sendBeacon
并不会立即执行,可以说它会在空闲时间发送请求。- 能够发送跨域请求
navigator.sendBeacon
是不受跨域限制的
- 缺点
- 只能发送
POST
请求 - 只能传输少量数据(
64 KB
以内) - 无法自定义请求头
- 只能传输
ArrayBuffer
、ArrayBufferView
、Blob
、DOMString
、formData
或URLSearchParams
类型数据 - 如果处于危险网络环境、开启了广告屏蔽插件 该请求将无效。
发送心跳包
利用navigator.sendBeacon
发送心跳包,与服务器保持长连接,避免长时间未请求而断开连接。
1function sendHeartbeat() {
2 const data = 'heartbeat';
3 const url = 'http://localhost:3001/api/heartbeat';
4
5 navigator.sendBeacon(url, data);
6}
7
8
9setInterval(sendHeartbeat, 5000);
10
埋点
可以使用navigator.sendBeacon
在页面卸载时记录停留时间,以及pv、uv、错误日志的上报、按钮点击次数
等 用户反馈 对于一些小的表单,如:用户反馈、意见和建议
等可以使用navigator.sendBeacon
进行请求。
基本使用
1navigator.sendBeacon(url, data);
- url: 是要发送请求的目标地址,可以是相对路径或绝对 URL。
- data: 是要发送的数据,可以是字符串、ArrayBuffer 或 Blob。
navigator.sendBeacon 方法发送的请求是 POST 请求,并且请求头中会自动添加 Content-Type: application/x-www-form-urlencoded。
需要发送JSON格式的数据的时候,可以使用Blob进行包装从而发送JSON数据
1let data = {name:"smz"}
2let blob = new Blob([JSON.stringify(data)],{type:'application/json; charset=UTF-8'})
3
当打开页面时记录时间,在页面销毁的时候记录时间,这样就得到了用户停留时间,再通过navigator.sendBeacon
进行上报用户名、时间、页面等信息完成数据的统计。
前端:
1const reportData = () =>{
2
3 let startTime = performance.now();
4 let logVisit = async function() {
5 if (!navigator.sendBeacon) return false;
6
7 const endTime = performance.now();
8
9 let data = new FormData();
10 const reportDataList = {
11 name: 'smz',
12 page: 'home',
13 stayTime: ((endTime - startTime)/60000).toFixed(2) + '分钟'
14 };
15 let time = new Blob([JSON.stringify(reportDataList)],{type:'application/json; charset=UTF-8'})
16 navigator.sendBeacon("http://localhost:3001/api/b", time);
17 };
18 window.addEventListener("beforeunload", logVisit);
19}
20reportData()
21
后端:这里使用node
1const express = require('express')
2const app = express()
3
4app.use((req, res, next) => {
5 res.setHeader('Access-Control-Allow-Origin', 'http://localhost:63342');
6 res.setHeader('Access-Control-Allow-Credentials', true);
7 res.setHeader("Access-Control-Allow-Headers", "Content-Type,XFILENAME,XFILECATEGORY,XFILESIZE");
8 next();
9});
10
11
12app.use(express.text())
13
14app.post('/api/heartbeat',(req,res)=>{
15 console.log(req.body)
16 res.send('ok')
17})
18
19
20app.use(express.json())
21
22
23app.post('/api/b',(req,res)=>{
24 console.log(req.body)
25 res.send('ok')
26})
27
28app.listen(3001,()=>{
29 console.log('server is running')
30})
31
总结:
总结
总之,navigator.sendBeacon
是一个非常有用的 API
,在页面卸载或关闭时发送异步请求,非常适合发送统计数据、日志记录、表单提交等场景。
个人笔记记录 2021 ~ 2025