JS Navigator.sendBeacon 可靠的、异步地向服务器发送数据

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Navigator.sendBeacon 是一个用于发送少量数据到服务器的 API,尤其适用于在页面即将卸载时发送数据,如日志记录、用户行为分析等。与传统的 AJAX 请求不同,sendBeacon 方法的设计目标是确保数据在页面卸载(例如用户关闭标签页或导航到新页面)时能够可靠地发送。Navigator.sendBeacon 方法可用于通过 HTTP POST 将少量数据异步传输到 Web 服务器。它主要用于将统计数据发送到 Web 服务器,同时避免了用传统技术(如:XMLHttpRequest)发送分析数据的一些问题。

一、Navigator.sendBeacon 是什么&能做什么?


Navigator.sendBeacon 是一个用于发送少量数据到服务器的 API,尤其适用于在页面即将卸载时发送数据,如日志记录、用户行为分析等。

与传统的 AJAX 请求不同,sendBeacon 方法的设计目标是确保数据在页面卸载(例如用户关闭标签页或导航到新页面)时能够可靠地发送。

Navigator.sendBeacon 方法可用于通过 HTTP POST 将少量数据异步传输到 Web 服务器。

它主要用于将统计数据发送到 Web 服务器,同时避免了用传统技术(如:XMLHttpRequest)发送分析数据的一些问题。

二、Navigator.sendBeacon 详细介绍

1、使用场景

  1. 页面卸载时的日志记录:在用户离开页面时记录行为数据,如页面停留时间、点击行为等。
  2. 分析和监控:发送用户行为数据到分析服务器,用于网站性能监控和用户行为分析。
  3. 状态报告:向服务器报告应用程序状态或错误信息。

2、不使用 Navigator.sendBeacon 时,如何处理?

  1. 发起一个同步 XMLHttpRequest 来发送数据(open() 方法的第三个参数为 false)。
  2. 创建一个 <img> 元素并设置 src,大部分用户代理会延迟卸载(unload)文档以加载图像。
  3. 创建一个几秒的 no-op 循环。

3、不使用 Navigator.sendBeacon 可能会带来哪些问题?

3.1. 同步 XHR

  1. 同步请求会阻塞浏览器的主线程,导致页面在请求完成之前无法响应用户操作。这会严重影响用户体验,尤其是在请求需要较长时间才能完成时。
  2. 许多现代浏览器会对同步请求发出警告,提示开发者这种方法可能会导致性能问题,并建议改用异步请求。

3.2. 创建 img 元素

  1. 页面卸载流程被阻塞。
  2. 后面页面的加载时机被延迟,用户体验不好。

3.3. 创建循环

  1. 页面卸载流程被阻塞。
  2. 后面页面的加载时机被延迟,用户体验不好。

4、Navigator.sendBeacon 的优点

  1. 可靠性:sendBeacon 的主要设计目标是确保数据在页面卸载时能够可靠地发送。浏览器会在后台继续尝试发送数据,即使页面已经关闭或正在导航到新页面。
  2. 非阻塞:sendBeacon 方法是非阻塞的,不会阻碍页面的卸载过程。相比于传统的同步 AJAX 请求,不会影响用户体验或导致页面卸载延迟。
  3. 简单性:接口简单,只需提供目标 URL 和数据,无需处理响应。适用于只需要发送数据而不需要从服务器获取数据的场景。
  4. 安全性:与其他 AJAX 请求方法一样,sendBeacon 遵循同源策略,不能发送跨域请求,除非服务器设置了适当的 CORS 头。

5、使用限制

  1. 数据大小限制(通常为几十 KB),适用于发送少量数据。
  2. 因为数据大小有限,sendBeacon 不适合用于发送大量或大文件的数据。
  3. sendBeacon 方法始终使用 HTTP POST 请求。
  4. 不返回响应,不提供处理服务器响应的机制,无法检查请求是否成功以及服务器的返回结果。

6、浏览器兼容性

Navigator.sendBeacon 支持主流的现代浏览器,包括 ChromeFirefoxSafariEdge 等,但不支持较老的浏览器(如 IE 11 及更早版本)。

三、Navigator.sendBeacon 如何使用

1、语法

navigator.sendBeacon(url);
navigator.sendBeacon(url, data);

2、参数

2.1. url

url 参数表明 data 将要被发送到的网络地址。

2.2. data 可选

data 参数是将要发送的 ArrayBufferArrayBufferViewBlobDOMStringFormDataURLSearchParams 类型的数据。

3、返回值

类型:boolean

当用户代理成功把数据加入传输队列时,sendBeacon() 方法将会返回 true,否则返回 false

4、Navigator.sendBeacon 使用举例

4.1. 参数格式为 ArrayBuffer

适用于传递二进制数据,如文件或图像片段。

const buffer = new ArrayBuffer(8);
navigator.sendBeacon('/log', buffer);

4.2. 参数格式为 ArrayBufferView

ArrayBufferView 是一种表示二进制数据视图的类型。常见的 ArrayBufferView 类型包括 Uint8Array, Int8Array, Uint16Array, Int16Array, Uint32Array, Int32Array, Float32Array, Float64Array 等等。


// 创建一个包含字符串的 Uint8Array
const text = 'Hello, world!';
const textEncoder = new TextEncoder();
const textArray = textEncoder.encode(text); // 将字符串编码为 Uint8Array
// 创建一个包含其他二进制数据的 Uint8Array
const binaryData = new Uint8Array([1, 2, 3, 4, 5]);
// 将两部分数据合并到一个大的 Uint8Array
const combinedArray = new Uint8Array(textArray.length + binaryData.length);
combinedArray.set(textArray, 0);
combinedArray.set(binaryData, textArray.length);
// 发送合并后的 Uint8Array
navigator.sendBeacon('xxx/xxx', combinedArray);

4.3. 参数格式为 Blob

适用于传递文件或其他大块的二进制数据。


const blob = new Blob(['user=gqk'], { type: 'text/plain' });
navigator.sendBeacon('xxx/xxx', blob);

4.4. 参数格式为 DOMString

适用于简单的文本数据。


navigator.sendBeacon('xxx/xxx', 'this is sendBeacon case');

4.5. 参数格式为 FormData

适用于发送表单内容或复杂的键值对数据。


const formData = new FormData();
formData.append('user', 'gqk');
navigator.sendBeacon('xxx/xxx', formData);

4.6. 参数格式为 URLSearchParams

适用于发送 URL 编码的查询参数。


const params = new URLSearchParams();
params.append('user', 'gqk');
navigator.sendBeacon('xxx/xxx', params);


四、Navigator.sendBeacon 和 XHR、fetch 有什么异同点

1、相同点

  1. 发送网络请求:所有这三种方法都用于从客户端向服务器发送数据。
  2. 支持多种数据格式:它们都可以发送字符串、JSON、二进制数据等多种格式的数据。

2、不同点

2.1. Navigator.sendBeacon

  1. 用于在页面卸载时发送少量数据,适合日志、分析数据等用途。
  2. 发送数据是异步的,但不返回任何信息给调用者,无法处理服务器的响应。
  3. 设计为在页面卸载时保证数据发送,即使在浏览器关闭或页面跳转时。
  4. 始终使用 HTTP POST 请求。
  5. 不需要处理响应,使用简单。

2.2. XMLHttpRequest

  1. 用于更复杂的、需要处理响应的 AJAX 请求。
  2. 可以进行同步或异步请求。
  3. 可以处理服务器的响应,并进行进一步处理(如解析 JSON、处理状态码等)。
  4. 提供丰富的事件(如 onloadonerroronprogress 等),可以监控请求的各个阶段。
  5. 在所有主流浏览器中都得到了广泛支持,包括一些较老的浏览器。
  6. 使用较复杂,需要处理请求的各个阶段和状态。

2.3. Fetch

  1. 现代化的请求接口,用于替代 XMLHttpRequest,支持更简单和更灵活的请求和响应处理。
  2. 始终进行异步请求,返回 Promise 对象。
  3. 支持链式处理响应,可以轻松解析 JSON、处理状态码等。
  4. 支持 async/await 语法,更符合现代 JavaScript 开发习惯。
  5. 更好地支持跨域请求和 CORS(跨域资源共享)。
  6. 允许在请求中添加更多的选项(如自定义头部、请求方法等)。

3、三者使用场景

  • Navigator.sendBeacon:简单、适合在页面卸载时发送少量数据,不处理响应。
  • XHR:功能全面、适合复杂的 AJAX 请求,但使用较复杂。
  • Fetch:现代化接口,简洁灵活,适合处理复杂请求和响应。

五、总结

  1. Navigator.sendBeacon 是一个专为可靠性设计的 API,特别适用于在页面卸载时发送少量数据。
  2. 它具有简单、非阻塞、可靠等优点,特别适合日志记录和用户行为分析等场景。
  3. 发出的是异步请求,并且是 POST 请求。
  4. 只能判断出是否放入浏览器任务队列,不能判断是否发送成功。
  5. 无需处理返回值。
  6. 需要注意浏览器兼容问题。
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
打赏
0
1
1
0
5
分享
相关文章
网络通讯技术:HTTP POST协议用于发送本地压缩数据到服务器的方案。
总的来说,无论你是一名网络开发者,还是普通的IT工作人员,理解并掌握POST方法的运用是非常有价值的。它就像一艘快速,稳定,安全的大船,始终为我们在网络海洋中的冒险提供了可靠的支持。
43 22
|
6天前
服务器数据恢复—NTFS分区误格式化数据怎样挽回?
NTFS文件系统下格式化在理论上不会对数据造成太大影响,但有可能造成部分文件目录结构丢失的情况。下面介绍一个人为误操作导致服务器磁盘阵列中的NTFS文件系统分区被格式化后的服务器数据恢复案例。
JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等,array.map()的使用详解(附实际应用代码)
array.map()可以用来数据转换、创建派生数组、应用函数、链式调用、异步数据流处理、复杂API请求梳理、提供DOM操作、用来搜索和过滤等,比for好用太多了,主要是写法简单,并且非常直观,并且能提升代码的可读性,也就提升了Long Term代码的可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
最细最有条理解析:事件循环(消息循环)是什么?为什么JS需要异步
度一教育的袁进老师谈到他的理解:单线程是异步产生的原因,事件循环是异步的实现方式。 本质是因为渲染进程因为计算机图形学的限制,只能是单线程。所以需要“异步”这个技术思想来解决页面阻塞的问题,而“事件循环”是实现“异步”这个技术思想的最主要的技术手段。 但事件循环并不是全部的技术手段,比如Promise,虽然受事件循环管理,但是如果没有事件循环,单一Promise依然能实现异步不是吗? 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您
JavaScript中通过array.filter()实现数组的数据筛选、数据清洗和链式调用,JS中数组过滤器的使用详解(附实际应用代码)
用array.filter()来实现数据筛选、数据清洗和链式调用,相对于for循环更加清晰,语义化强,能显著提升代码的可读性和可维护性。博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
如何在JavaScript中确定异步操作之间的依赖关系?
如何在JavaScript中确定异步操作之间的依赖关系?
31 1
有没有方法可以保证在JavaScript中多个异步操作的执行顺序?
有没有方法可以保证在JavaScript中多个异步操作的执行顺序?
89 58
服务器感染了.baxia勒索病毒,如何确保数据文件完整恢复?
近年来,勒索病毒如.baxia不断演变,利用漏洞、社交工程等手段加密文件,威胁范围扩大。加密货币的兴起使其支付方式更匿名,追踪困难。技术支持尤为重要,添加技术服务号(shuju315),专业团队提供数据恢复方案。面对复杂解密要求,包括赎金支付、个人信息提供和执行特定操作,需保持冷静并寻求帮助。防御措施包括加强安全意识、定期备份数据、安装杀毒软件、避免未知文件、更新系统及制定应急响应计划。
107 11
Node.js作为一种快速、可扩展的服务器端运行时环境
Node.js作为一种快速、可扩展的服务器端运行时环境
89 8