介绍下navigator.sendBeacon方法

navigator.sendBeacon() 是HTML5新增的一个API,用于在页面卸载(如关闭、刷新、跳转)时异步发送少量数据到服务器,且不会阻塞页面卸载或影响后续导航的加载性能。这在需要收集用户行为数据(如页面停留时间、按钮点击统计)的场景中特别有用。

一、核心特点

  1. 异步非阻塞:数据发送不会阻塞页面卸载流程,用户体验不受影响。
  2. 高可靠性:使用HTTP POST请求,浏览器确保在页面关闭前尝试发送数据。
  3. 小数据量优化:设计初衷是发送少量数据(通常<64KB),过大的数据可能被丢弃。
  4. 跨域支持:支持跨域请求,需服务器配置CORS。

二、基本语法

javascript 复制代码
const isSent = navigator.sendBeacon(url, data);
  • 参数
    • url:目标URL(字符串)。
    • data(可选):要发送的数据,可以是:
      • ArrayBuffer
      • ArrayBufferView(如Uint8Array
      • Blob/File
      • FormData
      • 字符串(如JSON、普通文本)
  • 返回值
    • true:浏览器已将请求加入发送队列。
    • false:队列已满或请求无法入队(如URL无效)。

三、典型应用场景

  1. 埋点统计

    javascript 复制代码
    window.addEventListener('unload', () => {
      const data = JSON.stringify({
        page: window.location.pathname,
       停留时间: performance.now(),
        点击事件: [...document.querySelectorAll('button')].map(btn => btn.id)
      });
      navigator.sendBeacon('/analytics', data);
    });
  2. 用户会话追踪

    javascript 复制代码
    document.addEventListener('visibilitychange', () => {
      if (document.visibilityState === 'hidden') {
        navigator.sendBeacon('/session-tracker', 'session-ended');
      }
    });
  3. 表单自动保存

    javascript 复制代码
    const formData = new FormData(document.getElementById('myForm'));
    window.addEventListener('beforeunload', () => {
      navigator.sendBeacon('/auto-save', formData);
    });

四、与其他请求方式的对比

特性 sendBeacon XMLHttpRequest/fetch
阻塞页面卸载 ❌ 不阻塞 ✅ 可能阻塞(同步请求)
请求优先级 低(后台排队) 高(可能影响新页面加载)
数据大小限制 通常<64KB 无明确限制
自动重试 ✅ 浏览器保证尝试发送 ❌ 需手动实现重试逻辑
适合场景 页面卸载时的小数据 实时数据交互

五、兼容性与替代方案

  1. 兼容性

    主流浏览器(Chrome 39+、Firefox 31+、Safari 11+、Edge 14+)均支持,IE不支持。

  2. 降级方案

    对于不支持的浏览器,可使用同步XMLHttpRequest(但会阻塞页面):

    javascript 复制代码
    function sendData(url, data) {
      if (navigator.sendBeacon) {
        return navigator.sendBeacon(url, data);
      } else {
        // 降级方案(注意:会阻塞页面)
        const xhr = new XMLHttpRequest();
        xhr.open('POST', url, false); // 第三个参数为false表示同步请求
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.send(data);
        return xhr.status === 200;
      }
    }

六、注意事项

  1. 数据格式

    • 发送JSON时需设置Content-Type(服务器端接收时需注意解析)。
    • 发送FormData时无需手动设置Content-Type,浏览器会自动处理。
  2. 服务器响应
    sendBeacon不关心服务器响应,无法获取返回值。

  3. 调试技巧

    • 在Chrome开发者工具的"Network"面板勾选"Preserve log"以查看卸载时的请求。
    • 使用visibilitychange事件代替unload/beforeunload,因为前者在页面进入后台(如切换标签)时触发,调试更方便。

七、面试延伸问题

  1. 为什么sendBeaconfetch更适合页面卸载时的数据发送?

    fetch默认是异步的,但页面卸载可能中断异步请求;而sendBeacon由浏览器保证在页面关闭前尝试发送。

  2. 如果需要发送大量数据(如1MB),sendBeacon是否合适?

    → 不合适,sendBeacon设计用于小数据,大数据可能被丢弃,建议使用fetch配合keepalive选项。

  3. 如何测试sendBeacon是否正常工作?

    → 可使用visibilitychange事件触发发送,在开发者工具中观察网络请求;或在服务器端记录接收情况。

八、现代替代方案(fetch + keepalive)

对于需要发送大量数据或获取响应的场景,可使用fetchkeepalive选项:

javascript 复制代码
window.addEventListener('unload', async () => {
  const data = await generateLargeData();
  await fetch('/api/upload', {
    method: 'POST',
    body: data,
    keepalive: true // 即使页面关闭也继续发送
  });
});

keepalive的兼容性与sendBeacon类似,但支持更大数据量和响应处理。

相关推荐
QQ1__8115175153 小时前
Spring boot名城小区物业管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
前端·vue.js·spring boot
钛态3 小时前
前端微前端架构:大项目的救命稻草还是自找麻烦?
前端·vue·react·web
一粒黑子3 小时前
【实战解析】阿里开源 PageAgent:纯前端 GUI Agent,一行JS让网页支持自然语言操控
前端·javascript·开源
独角鲸网络安全实验室3 小时前
2026微信小程序抓包全解析:从实操落地到合规风控,解锁前端调试新范式
前端·微信小程序·小程序·抓包·系统代理绕过·https证书严格校验·进程隔离
紫微AI3 小时前
前端文本测量成了卡死一切创新的最后瓶颈,pretext实现突破了
前端·人工智能·typescript
GISer_Jing3 小时前
AI前端(From豆包)
前端·aigc·ai编程
IT枫斗者3 小时前
前端部署后如何判断“页面是不是最新”?一套可落地的版本检测方案(适配 Vite/Vue/React/任意 SPA)
前端·javascript·vue.js·react.js·架构·bug
测试修炼手册3 小时前
[测试技术] 深入理解 JSON Web Token (JWT)
前端·json
AI老李3 小时前
2026 年 Web 前端开发的 8 个趋势!
前端
里欧跑得慢3 小时前
15. Web可访问性最佳实践:让每个用户都能平等访问
前端·css·flutter·web