前端数据上报方法方式

server/2025/2/8 17:18:26/

上报数据的时机

  • 页面加载时

此时进行数据上报,只需要在页面 load 时上报即可。

window.addEventListener('load', reportData, false);
  • 页面卸载或页面刷新时

此时进行数据上报,只需要在页面 beforeunload 时上报即可。

window.addEventListener('beforeunload', reportData, false);
  • SPA 路由切换时

如果是 vue-router 或 react-router@3 及以下版本,则可以在 hooks 里进行上报操作。

如果是 react-router@4 则需要在 Routes 根组件的生命周期内进行上报。

上报数据的方法

  1. 直接发请求上报
    我们可以直接将数据通过 ajax 发送到后端,以 axios 为例。
axios.post(url, data);

但这种方法有一个问题,就是在页面卸载或刷新时进行上报的话,请求可能会在浏览器关闭或重新加载前还未发送至服务端就被浏览器 cancel 掉,导致数据上报失败。

我们可以将 ajax 请求改为同步方法,这样就能保证请求一定能发送到服务端。由于 fetch 及 axios 都不支持同步请求,所以需要通过 XMLHttpRequest 发送同步请求。


const syncReport = (url, { data = {}, headers = {} } = {}) => {const xhr = new XMLHttpRequest();xhr.open('POST', url, false);xhr.withCredentials = true;Object.keys(headers).forEach((key) => {xhr.setRequestHeader(key, headers[key]);});xhr.send(JSON.stringify(data));};

这里要注意的是,将请求改为同步以后,会阻塞页面关闭或重新加载的过程,这样就会影响用户体验。

  1. 动态图片
    我们可以通过在 beforeunload 事件处理器中创建一个图片元素并设置它的 src 属性的方法来延迟卸载以保证数据的发送,因为绝大多数浏览器会延迟卸载以保证图片的载入,所以数据可以在卸载事件中发送。

const reportData = (url, data) => {let img = document.createElement('img');const params = [];Object.keys(data).forEach((key) => {params.push(`${key}=${encodeURIComponent(data[key])}`);});img.onload = () => img = null;img.src = `${url}?${params.join('&')}`;};

此时服务端可以返回一个 1px * 1px 的图片,保证触发 img 的 onload 事件,但如果某些浏览器在实现上无法保证图片的载入,就会导致上报数据的丢失。

  1. sendBeacon

为了解决上述问题,便有了 navigator.sendBeacon 方法,使用该方法发送请求,可以保证数据有效送达,且不会阻塞页面的卸载或加载,并且编码比起上述方法更加简单

用法如下:

navigator.sendBeacon(url, data);

url 就是上报地址,data 可以是 ArrayBufferView,Blob,DOMString 或 Formdata,根据官方规范,需要 request header 为 CORS-safelisted-request-header,在这里则需要保证 Content-Type 为以下三种之一:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

我们一般会用到 DOMString , Blob 和 Formdata 这三种对象作为数据发送到后端,下面以这三种方式为例进行说明。

DOMString

如果数据类型是 string,则可以直接上报,此时该请求会自动设置请求头的 Content-Type 为 text/plain。

const reportData = (url, data) => {navigator.sendBeacon(url, data);};

Blob

如果用 Blob 发送数据,这时需要我们手动设置 Blob 的 MIME type,一般设置为 application/x-www-form-urlencoded。

const reportData = (url, data) => {const blob = new Blob([JSON.stringify(data), {type: 'application/x-www-form-urlencoded',}]);navigator.sendBeacon(url, blob);};

Formdata

可以直接创建一个新的 Formdata,此时该请求会自动设置请求头的 Content-Type 为 multipart/form-data。

const reportData = (url, data) => {const formData = new FormData();Object.keys(data).forEach((key) => {let value = data[key];if (typeof value !== 'string') {// formData只能append string 或 Blobvalue = JSON.stringify(value);}formData.append(key, value);});navigator.sendBeacon(url, formData);};

注意这里的 JSON.stringify 操作,服务端需要将数据进行 parse 才能得到正确的数据。

总结

我们可以使用 sendBeacon 发送数据,这一方法既能保证数据可靠性,也不影响用户体验,如果浏览器不支持该方法,则可以降级使用同步的 ajax 发送数据。


http://www.ppmy.cn/server/165994.html

相关文章

Linux系统安装Nginx详解(适用于CentOS 7)

目录 1. 更新系统包 2. 安装EPEL仓库 3. 安装Nginx 4. 启动Nginx服务 5. 设置Nginx开机自启 6. 检查Nginx状态 7. 配置防火墙 8. 访问Nginx默认页面 9. 配置Nginx(可选) 10. 重启Nginx 解决步骤 1. 检查系统版本 2. 移除错误的 Nginx 仓库 …

QWidget中嵌入QQuickWidget,从qml端鼠标获取经纬度点(double类型),发到c++端。把c++端的对象暴露个qml端调用

qml端鼠标选取点 c端接收 c端 先写一个类&#xff0c;专门用来接收&#xff0c;取名MouseDrawAirspace #ifndef MOUSEDRAWAIRSPACE_H #define MOUSEDRAWAIRSPACE_H#include <QVariant> #include <QObject> #include <QGeoCoordinate> #include <QDebu…

GitHub 使用教程:从入门到进阶

1. GitHub账号注册 访问 GitHub 官网 (https://github.com)点击 “Sign up” 按钮填写用户名、邮箱和密码验证邮箱完成注册 2. 基础配置 2.1 安装Git 访问 Git 官网下载安装包运行安装程序&#xff0c;按提示完成安装打开终端&#xff0c;设置用户信息&#xff1a; git co…

34.Word:公积金管理中心文员小谢【35】

目录 Word2.docx​ 业务网点素材.docx​ Wordl.docx邮件合并​ Word2.docx F12/另存为&#xff1a;考生文件夹&#xff1a;Word2.docx 布局样式的复制 插入公式&#xff1a;插入→公式→整体大纲→细节&#xff1a;下标/分式/上标/点/括号&#xff08;❌不能手动输入括号&am…

centos虚拟机迁移没有ip的问题

故事背景&#xff0c;我们的centos虚拟机本来是好好的&#xff0c;但是拷贝到其他电脑上就不能分配ip&#xff0c;我个人觉得这个vmware他们软件应该搞定这个啊&#xff0c;因为这个问题是每次都会出现的。 网络选桥接 网络启动失败 service network restart Restarting netw…

CVPR2021 | VMI-FGSM VNI-FGSM | 通过方差调整增强对抗攻击的可迁移性

Enhancing the Transferability of Adversarial Attacks through Variance Tuning 摘要-Abstract引言-Introduction相关工作-Related Work方法-Methodology动机-Motivation基于方差调整的梯度攻击-Variance Tuning Gradient-based Attacks不同攻击的关系-Relationships among V…

tolua[一]框架搭建,运行example

一.安装tolua https://github.com/topameng/tolua 下载LuaFramework_UGUI的zip 将Assets目录拷贝到项目根目录下 提示确认注册&#xff0c;遇到这个对话框点确定即可 生成如下目录 二.LuaFramework->Build Windows Resource 接下来的目标是将这个main场景跑起来 需要先执行…

PHP PDO 教程

PHP PDO 教程 概述 PHP PDO&#xff08;PHP Data Objects&#xff09;扩展为PHP提供了数据访问抽象层。PDO可以让你使用相同的接口访问多种数据库系统&#xff0c;这大大简化了数据库操作。本文将详细介绍PHP PDO的基本用法、优势以及在实际开发中的应用。 ##PDO 简介 PDO是…