【小程序websocket最佳实践,有心跳和断线重连】

小程序websocket最佳实践,有心跳和断线重连

封装了WebSocketHandler类,用于管理websocket链接,保证链接的稳定和可靠,该类主要适用于小程序,但其设计思想和方法也适用于其他平台。

export default class WebSocketHandler {
  constructor() {
    // 获取环境变量
    this.env = wx.getStorageSync('env');
    // 生产环境的 WebSocket 地址
    this.prod = 'www.xx.com';
    // 开发环境的 WebSocket 地址
    this.dev = 'www.xx.com';
    // 根据环境变量选择 WebSocket 地址
    this.path = `${(this.env == 'pro' || !this.env) ? this.prod : this.dev}`;
    // 构建 WebSocket URL
    this.url = `wss://${this.path}/websocket`;
    // 重连次数限制
    this.limit = 0;
    // WebSocket 连接状态标志
    this.isClose = true;
    // 存储未发送的消息
    this.preParams = '';
    // 重连锁
    this.lockReconnect = false;
    // 重连定时器
    this.timer = null;

    // 心跳检测机制
    this.heartCheck = {
      timeout: 3000, // 心跳检测间隔
      timeoutObj: null, // 客户端定时器
      serverTimeoutObj: null, // 服务端定时器
      reset: function () {
        // 重置定时器
        clearTimeout(this.timeoutObj);
        clearTimeout(this.serverTimeoutObj);
        return this;
      },
      start: () => {
        // 启动心跳检测
        this.heartCheck.timeoutObj = setTimeout(() => {
          // 发送 PING 消息
          wx.sendSocketMessage({
            data: "PING",
            success() {
              // 发送成功
            }
          });
          // 设置服务端定时器,如果超时则关闭连接
          this.heartCheck.serverTimeoutObj = setTimeout(() => {
            wx.closeSocket();
          }, this.heartCheck.timeout);
        }, this.heartCheck.timeout);
      }
    };

    // 绑定 WebSocket 事件处理函数
    this._onSocketOpen();
    this._onSocketMessage();
    this._onSocketError();
    this._onSocketClose();
  }

  /**
   * 创建 WebSocket 连接
   * @param {Object} options - 建立连接时需要的配置信息
   * @param {string} options.userId - 用户 ID
   * @param {string} options.agentId - 代理 ID
   */
  connect({ userId}) {
    if (!this.isClose) {
      logger.info('WebSocket is already connected or connecting.');
      return;
    }
    wx.connectSocket({
      url: `${this.url}/${userId}`,
      header: {
        'content-type': 'application/json'
      },
      method: 'POST'
    });
  }

  /**
   * 发送消息
   * @param {Object} params - 要发送的消息参数
   * @returns {Promise} - 返回一个 Promise,表示消息发送的结果
   */
  send(params) {
    return new Promise((resolve, reject) => {
      const cruParams = JSON.stringify(params);
      if (this.isClose) {
        this.preParams = params;
        return;
      }
      logger.debug(`send---`, JSON.stringify(cruParams));
      wx.sendSocketMessage({
        data: cruParams,
        success: (res) => {
          logger.debug('sendSocketMessage', JSON.stringify(res));
          resolve({ res });
        },
        fail: (res) => {
          logger.error('sendSocketMessage', JSON.stringify(res));
          reject(res);
        },
      });
    });
  }

  /**
   * 关闭 WebSocket 连接
   */
  closeConnection() {
    this.isClose = true;
    wx.closeSocket();
  }

  /**
   * 处理 WebSocket 错误事件
   */
  _onSocketError() {
    wx.onSocketError((res) => {
      this.isClose = true;
      logger.error('WebSocket连接打开失败,请检查!', JSON.stringify(res));
      this.reconnect();
    });
  }

  /**
   * 处理 WebSocket 关闭事件
   */
  _onSocketClose() {
    wx.onSocketClose((res) => {
      this.isClose = true;
      logger.error('WebSocket 已关闭!', JSON.stringify(res));
      this.reconnect();
    });
  }

  /**
   * 处理 WebSocket 打开事件
   */
  _onSocketOpen() {
    wx.onSocketOpen(() => {
      logger.debug('WebSocket连接已打开!');
      this.heartCheck.reset().start();
      if (this.isClose && this.preParams) {
        logger.info('重新发送WebSocket消息!');
        wx.sendSocketMessage({
          data: JSON.stringify(this.preParams),
          success: () => {
            logger.debug('重新发送--sendSocketMessage', JSON.stringify(this.preParams));
            this.preParams = '';
          },
          fail: (res) => {
            logger.error('重新发送--sendSocketMessage-fail', JSON.stringify(res));
          },
        });
      } else {
        wx.sendSocketMessage({
          data: "PING",
        });
      }
      this.isClose = false;
    });
  }

  /**
   * 处理 WebSocket 消息事件
   */
  _onSocketMessage() {
    wx.onSocketMessage((res) => {
      if (res.data == "PONG") {
        console.log('PONG成功');
        this.heartCheck.reset().start();
      }
    });
  }

  /**
   * 尝试重新连接 WebSocket
   */
  reconnect() {
    if (this.lockReconnect) return;
    this.lockReconnect = true;
    clearTimeout(this.timer);
    if (this.limit < 50) {
      this.timer = setTimeout(() => {
        this.lockReconnect = false;
      }, 300);
      this.limit = this.limit + 1;
    }
  }
}
// 使用时
this.wsHandler = new WebSocketHandler();
app.wsHandler.send(params).then();

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【含文档】基于Springboot+微信小程序 的中心医院用户移动端(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…

全志科技发布T536高性能智慧工业芯片,飞凌嵌入式率先推出配套核心板

2024年9月24日下午&#xff0c;全志科技在中国国际工业博览会上成功举办了其最新产品——T536高性能智慧工业芯片的全球首发发布会。这款芯片采用创新的4核Cortex-A55与RISC-V混合架构&#xff0c;主频分别达到1.6GHz和600MHz&#xff0c;并集成了2TOPS算力的NPU&#xff0c;吸…

生信初学者教程(四):软件

文章目录 RRstudioLinux系统其他软件本书是使用R语言编写的教程,用户需要下载R和RStudio软件用于进行分析。 版权归生信学习者所有,禁止商业和盗版使用,侵权必究 R R语言是一种免费的统计计算和图形化编程语言,是一种用于数据分析和统计建模的强大工具。它具有丰富的统计…

耦合微带线单元的网络参量和等效电路公式推导

文档下载链接&#xff1a;耦合微带线单元的网络参量和等效电路资源-CSDN文库https://download.csdn.net/download/lu2289504634/89583027笔者水平有限&#xff0c;错误之处欢迎留言&#xff01; 一、耦合微带线奇偶模详细推导过程 二、2,4端口开路 三、2端口短路、3端口开路 四…

智能密码、指纹锁语音芯片ic方案 可存放40s语音内容 NVD语音芯片

随着科技的飞速发展&#xff0c;智能家居安全领域迎来了前所未有的变革。智能密码与指纹锁作为现代家庭安全防护的重要一环&#xff0c;其背后的语音芯片IC开发更是这一变革中的关键技术突破。 智能密码、指纹锁语音芯片ic方案 选型与简介&#xff1a; NVD语音芯片是一款低成…

quiz: python网络爬虫之规则1

下面答错了&#xff1a; B c 8A&#xff0c; 9A

STM32F407之超声波模块使用

#include "sys.h" #include "delay.h" #include "usart.h" #include "includes.h" #include "HC_SR04.h"int main() {OS_ERR err;//错误uart_init(9600);//串口初始化//超声波初始化HC_SR04();//OS初始化 他是第一个运行的函…

【大数据】数据中台怎么样助力企业创新和客户实践

在当今数字化时代&#xff0c;数据成为了企业竞争的关键因素。企业拥有大量的数据&#xff0c;但如何高效地利用这些数据&#xff0c;实现创新和提升客户体验&#xff0c;成为了一项重要的挑战。数据中台作为一种重要的数据管理和分析工具&#xff0c;发挥着关键的作用。本文将…

大数据毕业设计选题推荐-食品销售数据分析系统-Hive-Hadoop-Spark

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

数集相等定义凸显“R各元x的对应x+1的全体=R”是几百年重大错误

黄小宁 变量x所取各数也均由x代表&#xff0c;x代表其变域&#xff08;x所有能取的数组成的集&#xff09;内任一元。设集A&#xff5b;x&#xff5d;表A各元均由x代表&#xff0c;&#xff5b;x&#xff5d;中变量x的变域是A。其余类推。因各数x可是数轴上点的坐标所以x∈R变换…

AWS Network Firewall -NAT网关配置只应许白名单域名出入站

1. 创建防火墙 选择防火墙的归属子网&#xff08;选择公有子网&#xff09; 2. 创建规则白名单域名放行 3. 绑定相关规则 继续往下拉 绑定非托管规则 4. 配置网络路由 相关规则 参考图 解释 防火墙的归属公有子网路由表规则机器实例的规则子网路由表规则nat网管路…

springboot实战学习(7)(JWT令牌的组成、JWT令牌的使用与验证)

接着上篇博客的学习。上篇博客是在基本完成用户模块的注册接口的开发以及注册时的参数合法性校验的基础上&#xff0c;基本完成用户模块的登录接口的主逻辑以及提到了问题&#xff1a;"用户未登录&#xff0c;需要通过登录&#xff0c;获取到令牌进行登录认证&#xff0c;…

Linux 安装redis主从模式+哨兵模式3台节点

下载 https://download.redis.io/releases/ 解压 tar -zxvf redis-7.2.4.tar.gz -C /opt chmod 777 -R /opt/redis-7.2.4/安装 # 编译 make # 安装&#xff0c; 一定是大写PREFIX make PREFIX/opt/redis-7.2.4/redis/ install配置为系统服务 cd /etc/systemd/system/主服务…

一文上手SpringSecuirty【六】

自定义认证流程完成之后,前端收到了后端生成的token,那么在之后的所有请求当前,都必须携带token.作为服务器来说,得验证这个token,是否合法. 一、验证token是否合法 1.1 OncePerRequestFilter过滤器 OncePerRequestFilter是 Spring 框架中的一个过滤器&#xff0c;用于确保在…

基于nodejs+vue的校园二手物品交易系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

Rust 语言开发 ESP32C3 并在 Wokwi 电子模拟器上运行(esp-hal 非标准库、LCD1602、I2C)

文章目录 esp-rs 简介GithubRust 包仓库Wokwi 电子模拟器开发环境Rust 环境esp-rs 环境创建 ESP32C3 项目项目结构编译项目命令运行模拟器ESP32C3 烧录 esp-rs 简介 esp-rs 是一个专注于为 Espressif 系列芯片&#xff08;如 ESP32、ESP32-S2、ESP32-C3 等&#xff09;提供 Ru…

如何在 Three.js 场景中创建可点击展开的标签

在复杂的可视化场景中&#xff0c;经常需要为 3D 对象添加可交互的标签&#xff0c;以便用户点击时可以查看详细信息。这篇文章将通过一个简单的案例展示&#xff0c;如何在 Three.js 中为对象创建可点击的标签&#xff0c;点击标签可以展开详细信息&#xff0c;再次点击可以关…

论文复现:考虑电网交互的风电、光伏与电池互补调度运行(MATLAB-Yalmip-Cplex全代码)

论文复现:考虑电网交互的风电、光伏与电池储能互补调度运行(MATLAB-Yalmip-Cplex全代码) 针对风电、光伏与电化学储能电站互补运行的问题,已有大量通过启发式算法寻优的案例,但工程上更注重实用性和普适性。Yalmip工具箱则是一种基于MATLAB平台的优化软件工具箱,被广泛应用…

基于单片机语音智能导盲仪仿真设计

文章目录 前言资料获取设计介绍设计程序具体实现截图设计获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们…

【Python】探索 Graphene:Python 中的 GraphQL 框架

人们常说挣多挣少都要开心&#xff0c;这话我相信&#xff0c;但是请问挣少了怎么开心&#xff1f; 随着现代 Web 应用对数据交互需求的不断增长&#xff0c;GraphQL 作为一种数据查询和操作语言&#xff0c;越来越受到开发者的青睐。Graphene 是 Python 语言中实现 GraphQL 的…