长连接配置以及断线重连

news2024/12/28 18:53:02

目录

长连接index 主要进行连接

import SockJS from "sockjs-client";
import Stomp from "stompjs";
import { notification } from "antd";
// 网络请求API
import { nowApiAddressObj } from "../api/nowApiAddressObj";

// 工具
import YaoTokenUtil from "../utils/tokenTool";

notification.config({
  maxCount: 1,
  top: 50,
});
let webSocketJSTiem = null;
// 正在进行重新连接
let isReconnection = false;
function webSocketJS() {
  let socket = null;
  let stompClient = null;
  console.log("yaojunhao 测试测试我是计时器尝试重新连接2");

  return new Promise((resolve, reject) => {
    socket = new SockJS(`${nowApiAddressObj}/scream/api/ws`, null, {
      transports: ["websocket", "xhr-streaming", "xhr-polling"],
      withCredentials: true,
      log: false,
    });
    stompClient = Stomp.over(socket);

    let headers = {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Credentials": true,
      "Access-Control-Allow-Headers": "X-PINGOTHER, Content-Type",
      "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
      "X-Auth-Token": YaoTokenUtil.getToken() || "",
    };

    stompClient.onerror = (err) => {
      console.log("yaojunhao webSocketJS_onerror", err);
      reject(err);
    };

    function tokenError(code) {
      if (code === 1404) {
        // 清除token
        YaoTokenUtil.clearToken();
        // 跳转登录页面
        window.location.href = "/login";
        sessionStorage.setItem("userInfoLoseEfficacy", JSON.stringify(true));
      }
    }

    stompClient.connect(
      headers,
      (frame) => {
        clearTimeout(webSocketJSTiem);
        webSocketJSTiem = null;
        notification.success({
          message: "Api连接成功",
          showProgress: true,
          duration: 2,
        });

        console.log("yaojunhao webSocketJS_connect_连接成功");
        if (isReconnection) {
          location.reload();
        }
        // console.log(frame);
        resolve(stompClient);
      },
      (err) => {
        if (err?.headers?.message == "1404") {
          tokenError(parseInt(err.headers.message));
        } else {
          //连接失败进行重连
          stompClient.disconnect(
            () => {
              notification.error({
                message: "连接失败,正在尝试重新连接",
                showProgress: true,
                duration: 1,
              });
              console.log("STOMP连接已关闭");
              webSocketJSTiem = setTimeout(webSocketJS, 5000);
              isReconnection = true;
            },
            (error) => {
              console.error("关闭STOMP连接时发生错误:", error);
            }
          );
        }
        console.log("yaojunhao webSocketJS_connect_连接失败", err);
        reject(err);
      }
    );
  });
}

// 销毁定时器
function destroyTime() {
  clearTimeout(webSocketJSTiem);
  webSocketJSTiem = null;
}

export { webSocketJS, destroyTime };

其中一项 子项 链接成功后进行订阅


import { webSocketJS, destroyTime } from "../index";
import YaoBasicsUtil from "../../utils/basicsTool";

let stompClient = null;
// 用于保存订阅ID
let subscription = null;

class basketballSingle {
  // 创建webSocketJS
  async createStompClient() {
    stompClient = await webSocketJS();
    console.log("yaojunhao createStompClient_stompClient", stompClient);
  }
  // 订阅消息,并保存订阅ID
  async subscribe(fun) {
    subscription = stompClient.subscribe(
      `/topic/bkSingle/${
        JSON.parse(localStorage.getItem("userTokenInfo"))?.sub
      }`,
      (msg) => {
        console.log("广播成功");
        console.log("yaojunhao 测试测试订阅消息", msg);
        const messagesData = YaoBasicsUtil.jsonStringToJsonObj(msg.body);
        // 给每个参数都添加索引key作为主键
        messagesData.map((item, index) => {
          item.idIndex = index;
        });
        console.log("yaojunhao 测试测试订阅消息转换", messagesData);
        fun(messagesData);
      }
    );
    return subscription;
  }

  // 长链接取消订阅的函数
  unsubscribeFromTopic() {
    destroyTime();
    if (subscription) {
      stompClient.unsubscribe(subscription.id);
      console.log("yaojunhao webSocketJS_已取消订阅");
      // 清理subscription变量,避免内存泄漏
      subscription = null;
    }
  }
}

const basketballSingleSocket = new basketballSingle();
export default basketballSingleSocket;

注意 在页面里必须先连接 再订阅

  // 页面加载完毕时
  useEffect(() => {
    messageApi.open({
      key: messageSinkStateKey,
      type: "loading",
      content: "当前是历史数据,正在获取最新数据",
      duration: 0,
    });
    setSimulationData([...basketballSingleData]);
    console.log(
      "yaojunhao 页面加载完毕时 basketballSingleData",
      basketballSingleData
    );

    // 订阅长连接
    async function getSubscriptionId() {
      await basketballSingle.subscribe((e) => {
        // 判断是不是首次进入
        if (!messageSinkState) {
          messageApi.destroy(messageSinkStateKey);
          messageApi.open({
            key: messageSinkStateKey,
            type: "success",
            content: "成功获取到新数据",
            duration: 2,
          });
          messageSinkState = true;
        }
        console.log("yaojunhao basketballSingle_订阅消息转换", e);

        // 保存到仓库
        dispatch(setBasketballSingleData([...e]));
        setSimulationData([...e]);

        // 设置弹出层中展示数据
        setPopupData({ ...e[popupDataIndex] });
        dispatch(setBasketballSingleModalData({ ...e[popupDataIndex] }));
        console.log("yaojunhao 保存数据 重新渲染页面", [...e]);
      }).id;
    }
    async function createStompClient() {
      await basketballSingle.createStompClient();
      getSubscriptionId();
    }
    createStompClient();
    return () => {
      console.log("yaojunhao 组件销毁时取消订阅");
      basketballSingle.unsubscribeFromTopic();
    };
  }, []); // 空依赖数组表示这个effect只在组件挂载时运行一次

原理

  1. 连接失败后会进入stompClient.connect的(err) =>方法,在里面进行重连
  2. 重连成功后不会重新订阅,
    第一种,需要监视是否重新订阅成功,并且有几个页面就要监视几次,因为链接和订阅是不同的,浪费资源
    第二种,进行判断是否是重新订阅 如果是则重新刷新页面(我选择的是这种)

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

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

相关文章

LeetCode【0054】螺旋矩阵

本文目录 1 中文题目2 求解方法:数学模拟2.1 方法思路2.2 Python代码2.3 复杂度分析 3 题目总结 1 中文题目 给定一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 示例: 提示: 1 ≤ m …

万字长文解读深度学习——训练(DeepSpeed、Accelerate)、优化(蒸馏、剪枝、量化)、部署细节

🌺历史文章列表🌺 深度学习——优化算法、激活函数、归一化、正则化深度学习——权重初始化、评估指标、梯度消失和梯度爆炸深度学习——前向传播与反向传播、神经网络(前馈神经网络与反馈神经网络)、常见算法概要汇总万字长文解读…

C#版使用融合通信API发送手机短信息

目录 功能实现 范例运行环境 实现范例 类设计 类代码实现 调用范例 总结 功能实现 融合云通信服务平台,为企业提供全方位通信服务,发送手机短信是其一项核心功能,本文将讲述如何使用融合云服务API为终端手机用户发送短信信息&#xf…

第四十五章 Vue之Vuex模块化创建(module)

目录 一、引言 二、模块化拆分创建方式 三、模块化拆分完整代码 3.1. index.js 3.2. module1.js 3.3. module2.js 3.4. module3.js 3.5. main.js 3.6. App.vue 3.7. Son1.vue 3.8. Son2.vue 四、访问模块module的state ​五、访问模块中的getters ​六、mutati…

如何解决不能将开发板连接到虚拟机的问题(连接显示灰色,不能选中)

-- 如果连接上rk3588单片机,虚拟机无法来连接,如何更改 -- 先将虚拟机关机 -- 将虚拟机的配置文件以文本文件的形式打开 -- 再将所有的FALSE改为TRUE即可 -- 然后再次打开虚拟机即可

什么是白盒测试

一、什么是白盒测试 白盒测试又称结构测试、逻辑驱动测试或基于代码的测试。 白盒测试是一种测试用例设计方法,盒子指的是被测试的软件,白盒指的是盒子是可视的,即清楚盒子内部的东西以及里面是如何运作的。 "白盒"法需要测试者…

图形 2.6 伽马校正

伽马校正 B站视频:图形 2.6 伽马校正 文章目录 伽马校正颜色空间传递函数 Gamma校正校正过程为什么需要校正?CRT与转换函数 为什么sRGB在Gamma 0.45空间? 人对亮度的敏感韦伯定律中灰值 线性工作流不在线性空间下进行渲染的问题统一到线性空…

Android setContentView执行流程(一)-生成DecorView

Android setContentView执行流程(一)-生成DecorView Android setContentView执行流程(二)-将布局添加到mContentParent setContentView的流程主要就是讲在Activity的onCreate方法中调用setContentView方法之后,我们自定义的xml文件加载的过程,学习它可以…

【计算机网络】【网络层】【习题】

计算机网络-网络层-习题 文章目录 13. 图 4-69 给出了距离-向量协议工作过程,表(a)是路由表 R1 初始的路由表,表(b)是相邻路由器 R2 传送来的路由表。请写出 R1 更新后的路由表(c)。…

图像处理实验四(Adaptive Filter)

一、Adaptive Filter简介 自适应滤波器(Adaptive Filter)是一种能够根据输入信号的统计特性自动调整自身参数以达到最佳滤波效果的滤波器。它广泛应用于信号处理领域,如信道均衡、系统识别、声学回波抵消、生物医学、雷达、波束形成等模块。 …

typedef 与 extern 的结合:一场误解的澄清

typedef 与 extern 的结合:一场误解的澄清 一、typedef 的基本用法二、extern 的基本用法三、typedef 与 extern 的结合:一场误解的澄清示例二:使用 extern 声明外部变量示例三:错误的用法:尝试在 typedef 中使用 extern四、总结在C语言编程的世界里,typedef和extern是两…

Qt_day5_常用类

常用类 目录 1. QString 字符串类(掌握) 2. 容器类(掌握) 2.1 顺序容器QList 2.2 关联容器QMap 3. 几种Qt数据类型(熟悉) 3.1 跨平台数据类型 3.2 QVariant 统一数据类型 3.3 QStringList 字符串列表 4. QD…

HashMap的put流程知道吗

HashMap 的 put 方法算是 HashMap 中比较核心的功能了,复杂程度高但是算法巧妙,同时在上一版本的基础之上优化了存储结构,从链表逐步进化成了红黑树,以满足存取性能上的需要。本文逐行分析了 put 方法的执行流程,重点放…

鸿蒙UI开发——实现环形文字

1、背 景 有朋友提问:您好关于鸿蒙UI想咨询一个问题 如果我想实现展示环形文字是需要通过在Text组件中设置transition来实现么,还是需要通过其他方式来实现。 针对这位粉丝朋友的提问,我们做一下解答。 2、实现环形文字效果 ❓ 什么是环形…

保存pytest的执行日志;在日志中显示当前是第几次执行

1、在本地保存执行日志: 在终端中执行时因为指定了-s参数,所以会打印相关信息,可以帮助我们后续定位问题: 但是显示在终端时后面无法查看,所以需要把执行日志保存在本地,使用tee 或 重定向符号>&#x…

2024年8个最佳在线websocket调试工具选择

精选了 8 款功能强大且易于使用的 WebSocket 测试工具: 工具名称支持的系统是否免费ApifoxWindows, Mac, Linux是WebSocket KingWindows, Mac, Linux是PostmanWindows, Mac, Linux是Socket.IO Test ClientWindows, Mac, Linux是InsomniaWindows, Mac, Linux是Wires…

H5流媒体播放器EasyPlayer.js播放器wasm编译打包之后报uncaught referenceErro的原因排查

EasyPlayer.js H5播放器,是一款能够同时支持HTTP、HTTP-FLV、HLS(m3u8)、WS、WEBRTC、FMP4视频直播与视频点播等多种协议,支持H.264、H.265、AAC、G711A、Mp3等多种音视频编码格式,支持MSE、WASM、WebCodec等多种解码方…

初识算法 · 位运算(2)

目录 前言: 判定字符是否唯一 丢失的数字 比特位计数 只出现一次的数字III 前言: ​本文的主题是位运算,通过四道题目讲解,一道是判断字符是否唯一,一道是只出现一次的数字III,一道是比特位计数&…

丹摩征文活动 | 丹摩智算平台:服务器虚拟化的璀璨明珠与实战秘籍

丹摩DAMODEL|让AI开发更简单!算力租赁上丹摩! 目录 一、引言 二、丹摩智算平台概述 (一)平台架构 (二)平台特点 三、服务器虚拟化基础 (一)虚拟化的概念 &#xf…

[Docker#6] 镜像 | 常用命令 | 迁移镜像 | 压缩与共享

目录 Docker 镜像是什么 生活案例 为什么需要镜像 镜像命令详解 实验 1.一些操作 1. 遍历查看镜像 2. 查看镜像仓库在本地的存储信息 进入镜像存储目录 查看 repositories.json 文件 3. 镜像过滤 4. 下载镜像时的分层 实战一:离线迁移镜像 实战二&…