如何确保用户关闭网页时,关键数据100%发送到服务器?

更新日期: 2025-07-19 阅读: 1.1k 标签: 请求

用户关闭浏览器标签的瞬间,往往是数据上报的关键时刻。比如:

  • 电商平台需要记录用户离开前的最后浏览商品

  • 在线文档工具要自动保存未提交的草稿

  • 数据分析需捕获页面真实停留时长

但传统技术方案会失败:当页面卸载时,普通网络请求会被浏览器强制取消。下面通过真实案例,解析两种100%可靠的解决方案。


一、为什么普通请求会失败?

当用户关闭标签页,浏览器触发两个关键事件:

  1. pagehide(页面隐藏)

  2. unload(页面卸载)

此时若用fetch或XMLHttpRequest发送请求:

// 失败案例
window.addEventListener('unload', () => {
  fetch('/save-data') // 请求将被浏览器中断
});

根本原因:页面JS执行环境已被销毁,浏览器会主动终止未完成的请求。


二、过时的"暴力解法"及其危害

早期开发者使用同步XMLHttpRequest

// 已淘汰的方案!
const xhr = new XMLHttpRequest();
xhr.open('POST', '/save', false); // 第三个参数false表示同步
xhr.send(data);

致命缺陷

  • 完全阻塞主线程,导致页面卡死

  • 用户无法切换标签页,甚至无法关闭浏览器

  • 移动端可能触发系统警告

据统计,同步请求会使页面响应延迟300ms以上,用户体验极差。


三、现代方案一:navigator.sendBeacon()

这是浏览器专为"最后一刻"数据发送设计的api

核心优势

  • 不阻塞页面关闭

  • 浏览器保证请求发送

  • 使用简单

代码示例

window.addEventListener('pagehide', (event) => {
  // 检查是否进入bfcache(页面未真正关闭)
  if (event.persisted) return; 
  
  const logData = {
    duration: performance.now(),
    page: location.href
  };
  
  // 转换成Blob格式
  const blob = new Blob(
    [JSON.stringify(logData)], 
    { type: 'application/json' }
  );
  
  // 发送请求(无需等待响应)
  navigator.sendBeacon('/log', blob);
});

注意事项

特性限制说明
请求方法仅支持POST
请求头不可自定义
数据大小部分浏览器限制在64KB以内
响应处理无法获取服务器返回结果


四、现代方案二:Fetch API + keepalive

适合需要更多控制的场景:

window.addEventListener('pagehide', async (event) => {
  if (event.persisted) return;
  
  const draft = editor.getValue(); // 获取编辑器内容
  
  // 使用keepalive模式
  fetch('/api/save-draft', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ content: draft }),
    keepalive: true // 关键参数!
  });
});

与sendBeacon对比

能力sendBeaconfetch+keepalive
支持GET请求
自定义Header
发送FormData
跨域凭证携带

五、如何选择最佳方案?

根据业务需求决策:

  • 选 sendBeacon
    只需发送简单日志(如点击追踪/页面停留统计)

  • 选 fetch+keepalive
    需要保存用户数据(如文档草稿)、必须携带认证信息、需使用PUT/DELETE方法


六、真实场景中的避坑指南

  1. 事件监听优先用 pagehide
    unload 事件可能阻止浏览器使用往返缓存(bfcache),影响用户体验

  2. 重要数据需要双重保障

    // 提前在visibilitychange事件中发送
    document.addEventListener('visibilitychange', () => {
      if (document.visibilityState === 'hidden') {
        navigator.sendBeacon('/backup-data');
      }
    });
  3. 服务器端必须幂等处理
    因网络波动可能造成重复发送,服务端应做去重处理


七、特殊场景解决方案

场景1:需要发送超大数据
拆分数据 + 多次发送:

// 分段发送日志
const chunks = splitLargeData(data); 
chunks.forEach(chunk => {
  navigator.sendBeacon('/log-chunk', chunk);
});

场景2:低版本浏览器兼容

if (!navigator.sendBeacon) {
  // 回退方案:使用同步XHR(仅作保底)
  const xhr = new XMLHttpRequest();
  xhr.open('POST', url, false);
  xhr.send(data);
}


结语

通过sendBeacon和fetch+keepalive,开发者能在不影响用户体验的前提下,实现关闭页面的数据可靠上报。关键点在于:

  1. 优先选用浏览器原生方案

  2. 根据数据类型选择合适API

  3. 服务端做好数据幂等处理

最新统计显示,全球98%的浏览器已支持这两种方案,可放心用于生产环境。

实际部署前,建议使用Chrome DevTools的Application > Background services模块测试请求发送状态,确保万无一失。

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://fly63.com/article/detial/12876

相关推荐

flutter之网络请求dio封装,拦截器的封装

flutter一直很火的网络请求插件dio,直接上代码,写成一个类,可以直接使用,包含请求的封装,拦截器的封装

ajax异步请求302分析

遇到这样一种情况,打开网页两个窗口a,b(都是已经登录授权的),在a页面中退出登录,然后在b页面执行增删改查,这个时候因为授权原因,b页面后端的请求肯定出现异常(对这个异常的处理,进行内部跳转处理),b页面中的ajax请求的回调中就会出现问题

nginx 301跳转https后post请求失效问题解决

强制把http请求跳转到https,结果发现App有部分的功能不能使用,因为App一共设置了4种请求方式,分别是GET,POST,DELETE和OPTIONS方式,设置301跳转后所有的请求方法都变成了GET方式,导致一些功能无法正常使用.

Js两个异步请求 同步合并数据

业务代码经常会有 两个不一样的请求,拿到数据后合并成新数组的操作。但是在异步请求中我们不知道哪个请求的回调更快返回,从而使代码的合并时间无法确定。这就需要在两个异步请求都完成后再做数据处理。

http请求过程的7个步骤

HTTP通信机制是在一次完整的HTTP通信过程中,Web浏览器与Web服务器之间将完成下列7个步骤:建立TCP连接、Web浏览器向Web服务器发送请求命令、Web浏览器发送请求头信息、 Web服务器应答

http请求的几种类型

http请求中的8种请求方法:opions 返回服务器针对特定资源所支持的HTML请求方法 ,Get 向特定资源发出请求,Post 向指定资源提交数据进行处理请求

node.js含有%百分号时,发送get请求时浏览器地址自动编码的问题

目前浏览器会对地址,进行编码,比如这个文件名:在发到后台时,会自动编码成:不过如果文件名中含有%百分号,编码过程则会出现问题,如

HTTP请求报文和响应报文

GET:请求获取Request—URL所标识的资源,POST:在Request—URL所标识的资源后附加资源,HEAD:请求获取由Request—URL所标识的资源的响应消息报头,PUT:请求服务器存储一个资源,由Request—URL作为其标识

ajax中options请求的理解

这个概念听着有点耳生,嗯是我自己这么说的。我们可以把浏览器自主发起的行为称之为“浏览器级行为”。之所以说options是一种浏览器级行为,是因为在某些情况下,普通的get或者post请求回首先自动发起一次options请求

HTTP请求的11个处理阶段

几乎所以有关Nginx书只要是讲深入点的就会讲到Nginx请求的11个处理阶段,要记住这些真是不易,人脑特别不擅长记住各种东西,只能做些索引罢了,能做到知道这个知识点在哪儿能找到不就行了,可是你去面试还是问这些理论,所以这里汇总下记录如下

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!