js 在浏览器窗口关闭后还可以不中断网络请求

news2024/11/23 0:23:38

有个需求,我们需要在用户发送数据过程中,如果用户关闭了网页(包括整个浏览器关闭),不要中断数据传递

目前XMLHttpRequest对象是不支持的

http服务器

为了测试效果我们用nodejs写了个http服务器代码 文件名为httpServer.js如下,执行node httpServer.js就可以跑起来,支持get,post携带数据

// 导入http模块
const http = require('http');
var querystring = require('querystring');
// 创建Web服务器对象
const server = http.createServer();
// 监听端口号5005并启动HTTP服务器
server.listen(5005, () => {
    console.log('Web服务器启动成功啦!')
})

// 服务器实例通过.on()方法为服务器绑定request事件,监听客户端发来的请求,触发事件处理函数
server.on('request', (req, res) => {
    const version = req.httpVersion;
    const url = req.url;
    const method = req.method;
    console.log("收到请求:" + url + "method:" + method)
    res.setHeader('Content-Type', 'application/json');
    res.setHeader("Access-Control-Allow-Origin", '*')

    let info = { url: url, method: method }

    if (method.toLocaleLowerCase() == "post") {
        // 定义了一个post变量,用于暂存请求体的信息
        var post = '';

        // 通过req的data事件监听函数,每当接受到请求体的数据,就累加到post变量中
        req.on('data', function (chunk) {
            post += chunk;
        });

        // 在end事件触发后,通过querystring.parse将post解析为真正的POST请求格式,然后向客户端返回。
        req.on('end', function () {
            post = JSON.parse(post);
            info.body = post;
            console.log("post", post)
            // 调用res.end()方法向客户端响应一些内容
            res.end(JSON.stringify(info));
        });
    }
    else {
        // 调用res.end()方法向客户端响应一些内容
        res.end(JSON.stringify(info));
    }




})

终端效果

如果服务器收到网络请求,你的cmd或终端会看到如下的信息

我们写了三个网络请求函数

XMLHttpRequest请求

 function ajaxFn() {
            return new Promise((resolve, reject) => {
                var request = new XMLHttpRequest();

                request.open('get', request_url);
                request.send();
                request.onreadystatechange = function () {
                    if (request.readyState == 4) {
                        // console.log(request.responseText)
                        // console.log("ajax响应内容", request.responseText)
                        resolve(JSON.parse(request.responseText))
                    }
                }
                request.onerror = function (e) {
                    console.error("ajax跨域")
                    reject(2)
                }
            })
        }

调用方式

//XMLHttpRequest关闭窗口后不会发起网络请求
            ajaxFn().then(res=>{
                console.log("ajax响应内容",res)
            })

fetch请求 &&调用

//fetch 开启keepalive,可以发起网络请求,且不局限类型
            fetch(request_url, {
                method: 'post',
                keepalive: true,
                body: JSON.stringify({
                    'name': 'lili'
                })
            }).then(response => {
                response.json().then((data) => {
                    console.log("fetch响应内容",data);
                    return data;
                }).catch((err) => {
                    console.log(err);
                })
            })

 navigator.sendBeacon发送数据

  navigator.sendBeacon(request_url, JSON.stringify({ name: "sendBeacon" }), true);

为什么这里叫发送数据了,因为它不提供响应数据的回调函数,目标就是使用发送数据,只要服务器接口存在,关闭浏览器都不会影响继续发送数据

写个按钮,点击时候分不触发上面的函数,结果都可以发送数据

改为页面即将销毁时候触发上面函数

window.addEventListener('unload', function (event) {
            //触发函数
        });

结果XMLHttpRequest方式请求数据的方式,后台无法接受到数据

移动端兼容

unload事件在移动端上面不支持可以做以下判断

if (window.onunload) {
            window.addEventListener('unload', function (event) {
                //........
            });
        }
        else{
            document.addEventListener('visibilitychange', function logData() {
            if (document.visibilityState === 'hidden') {
                ///.....
            }
        });
 }

结论

使用navigator.sendBeacon场景:

  1. 传递少量数据
  2. 不考虑响应结果
  3. 只要求post请求方式
  4. 浏览器窗口关闭依旧发送数据
  5. 不会阻塞页面卸载,也就不会影响下一导航的载入
  6. 支持跨域(不关心数据响应,也没有跨域的顾虑,跨域是可以发送数据的,只是没法读取响应数据)
  7. 不支持自定义请求头

使用fetch keepalive

  1. 不考虑传递数据体积大小
  2. 大多数时候需要响应数据结果
  3. 任意请求方式
  4. 浏览器窗口关闭依旧发送数据&&不考虑响应结果

XMLHttpRequest
浏览器关闭后,不需要发送数据

参考

Navigator.sendBeacon() - Web API 接口参考 | MDN

Navigator sendBeacon页面关闭也能发送请求方法示例_javascript技巧_脚本之家

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/779502.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

获取大疆无人机的飞控记录数据并绘制曲线

机型M350RTK,其飞行记录文件为加密的,我的完善代码如下 gitgithub.com:huashu996/DJFlightRecordParsing2TXT.git 一、下载安装官方的DJIFlightRecord git clone gitgithub.com:dji-sdk/FlightRecordParsingLib.git飞行记录文件在打开【我的电脑】&am…

Windows nvm 安装后webstrom vue项目编译报错,无法识别node

1 nvm安装流程 卸载原先nodejs用管理员权限打开exe安装nvmnvm文件夹和nodejs文件夹 都授权Authenticated Users 完全控制nvm list availablenvm install 16.20.1nvm use 16.20.1输入node和npm检查版本命令,正常显示确认系统变量和用户变量都有nvm 和nodejs 2 bug情…

数学建模-聚类算法 系统(层次)聚类

绝对值距离:网状道路 一般用组间和组内距离 聚类的距离计算如何选取:看结果是否解释的通,选择一种结果解释的通的方法。

【数据挖掘】将NLP技术引入到股市分析

一、说明 在交易中实施的机器学习模型通常根据历史股票价格和其他定量数据进行训练,以预测未来的股票价格。但是,自然语言处理(NLP)使我们能够分析财务文档,例如10-k表格,以预测股票走势。 二、对自然语言处…

【转载+修改】pytorch中backward求梯度方法的具体解析

原则上,pytorch不支持张量对张量的求导,它只支持标量对张量的求导 我们先看标量对张量求导的情况 import torch xtorch.ones(2,2,requires_gradTrue) print(x) print(x.grad_fn)输出,由于x是被直接创建的,也就是说它是一个叶子节…

Vue.js uni-app 混合模式原生App webview与H5的交互

在现代移动应用开发中,原生App与H5页面之间的交互已经成为一个常见的需求。本文将介绍如何在Vue.js框架中实现原生App与H5页面之间的数据传递和方法调用。我们将通过一个简单的示例来展示如何实现这一功能。附完整源码下载地址:https://ext.dcloud.net.cn/plugin?i…

Java集成openAi的ChatGPT实战

效果图: 免费体验地址:AI智能助手 具体实现 public class OpenAiUtils {private static final Log LOG LogFactory.getLog(OpenAiUtils.class);private static OpenAiProxyService openAiProxyService;public OpenAiUtils(OpenAiProxyService openAiP…

【C++】入门 --- 命名空间

文章目录 🍪一、前言🍩1、C简介🍩2、C关键字 🍪二、命名冲突🍪三、命名空间🍩1、命名空间定义🍩2、命名空间的使用 🍪四、C输入&输出 🍪一、前言 本篇文章是《C 初阶…

Data Transfer Object-DTO,数据传输对象,前端参数设计多个数据表对象

涉及两张表的两个实体对象 用于在业务逻辑层和持久层(数据库访问层)之间传输数据。 DTO的主要目的是将多个实体(Entity)的部分属性或多个实体关联属性封装成一个对象,以便在业务层进行数据传输和处理,从而…

八、HAL_UART(串口)的接收和发送

1、开发环境 (1)Keil MDK: V5.38.0.0 (2)STM32CubeMX: V6.8.1 (3)MCU: STM32F407ZGT6 2、UART和USART的区别 2.1、UART (1)通用异步收发收发器:Universal Asynchronous Receiver/Transmitter)。 2.2、USART (1)通用同步异步收发器:Universal Syn…

【《R4编程入门与数据科学实战》——一本“能在日常生活中使用统计学”的书】

《R 4编程入门与数据科学实战》的两名作者均为从事编程以及教育方面的专家,他们用详尽的语言,以初学者的角度进行知识点的讲解,每个细节都手把手教学,以让读者悉数掌握所有知识点,在每章的结尾都安排理论与实操相结合的习题。与同…

banner轮播图实现、激活状态显示和分类列表渲染、解决路由缓存问题、使用逻辑函数拆分业务(一级分类)【Vue3】

一级分类 - banner轮播图实现 分类轮播图实现 分类轮播图和首页轮播图的区别只有一个,接口参数不同,其余逻辑完成一致 适配接口 export function getBannerAPI (params {}) {// 默认为1 商品为2const { distributionSite 1 } paramsreturn httpIn…

VTK是如何显示一个三维立体图像的

VTK是如何显示一个三维立体图像的 1、文字描述2、图像演示 1、文字描述 2、图像演示

MySQL-事务-介绍与操作

思考 假设在一个场景中,学工部解散了,需要删除该部门及该部门下的员工对应的SQL语句涉及的数据表信息如下 员工表 部门表 实现的SQL语句 -- todo 事务 -- 删除学工部 -- 删除1号部门 delete from tb_dept where id 1; -- 删除学工部下的员工 delete …

SPEC CPU 2006 docker gcc:4 静态编译版本 Ubuntu 22.04 LTS 测试报错Invalid Run

runspec.sh #!/bin/bash source shrc ulimit -s unlimited runspec -c gcc41.cfg -T all -n 1 int fp > runspec.log 2>&1 & tail -f runspec.log runspec.log 由于指定了-T all,导致-n 1 失效,用例运行了三次(后续验证&…

【LeetCode 75】 第十题(283)移动零

目录 题目: 示例: 分析: 代码运行结果: 题目: 示例: 分析: 给一个数组,要求将数组中的零都移动到数组的末尾. 首先我们可以遍历一边数组,遇到0的时候就在数组中把0删除,并且统计0的数量. 遍历完成以后数组中就没有0了,这时我们再在数组的后面添上之前统计的0的数量个0. …

IntelliJ IDEA Copyright添加

IDEA代码文件的版权(copyright)信息配置 1. 快速创建Copyright 版权配置文件 1.1 创建copyright文件 依次点击 File > Settings… > Editor > Copyright > 点击 “” 号或 “Add profile”***,弹出创建 Copyright Profile 操作窗口,在***文…

【iOS】App仿写--网易云音乐

文章目录 前言一、首页界面二、我的界面三、账号界面总结 前言 在暑假之前仿写了网易云app,一直没总结。 网易云app主要让我熟悉了视图之间的相互嵌套的用法与关系以及自定义cell的用法,特此撰写以下博客进行总结。 一、首页界面 首先来看一下完成的效…

深度挖掘《TCP与UDP》

文章目录 UDPTCPTCP特性TCP是如何实现的可靠传输?序号和确认序号为啥网络上会后发先至 什么是丢包,如何解决丢包?TCP建立连接:三次握手四次交互,为什叫三次握手?三次握手起到什么效果?达到什么目…

YZ06:加载项是否加载的判断

【分享成果,随喜正能量】人生,因有缘而聚,因情而暖;人生,因不珍惜而散,因恨而亡;活着就要善待自己,不属于自己的不强求,不是真心的不必喜欢,时间在变&#xf…