前端 实现webSocket封装

文章介绍了如何在HTTPS环境中处理WebSocket的心跳问题,包括错误参数导致的自动断开重连逻辑,以及WebSocket的生命周期管理和销毁方法。作者使用了一个名为UseWebsocket的类来实现这些功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于业务场景需要 写了个websocket

主要思想 :

      处理websocket 在https 环境下需要心跳来维持的问题 ;
      以及在默写特殊情况下 发错参数自动断开重连处理 
      和 生命周期结束或者需要自动销毁的处理
使用了class 进行编写业务场景需要的websocket;

import { baseWsUrl, baseWsUrl2 } from "./config";

export class UseWebsocket {
  constructor(
    url = null,
    ws = null,
    reconnect_current = 0,
    reconnect_timer = null,
    socket_open = false,
    hearbeat_timer = null,
    is_reonnect = true
  ) {
    // 存储webSocket实例对象
    this.ws = ws;
    this.url = baseWsUrl+ url;
    // 测试路径而已 正常用上面那条
    // this.url = baseWsUrl2 ;

    // 重连次数 我习惯设置3次
    this.reconnect_count = 3;

    // 当前重连次数
    this.reconnect_current = reconnect_current;
   
    // 是否自动重连
    this.is_reonnect = is_reonnect;
    // 开启标识
    this.socket_open = socket_open;

    // 心跳timer
    this.hearbeat_timer = hearbeat_timer;
    // 心跳发送频率
    this.hearbeat_interval = 5000;

    // 重连timer
    this.reconnect_timer = reconnect_timer;
    // 重连频率
    this.reconnect_interval = 3000;
  }

  initSocket() {
    if (!("WebSocket" in window)) {
      console.log("浏览器不支持WebSocket");
      return null;
    }

    if (this.ws) {
      return this.ws;
    }

    console.log("执行前查看地址===>", this, this.url);
    this.ws = new WebSocket(this.url);

    this.ws.onclose = (e) => {
      console.log("webSocket close 连接已断开", e, this);
      //  当连接断开的时候 其实就是webSocket 报错的时候 就可以去掉心跳的timer拉 并且修改标识
      clearInterval(this.hearbeat_timer);
      this.socket_open = false;

      if (this.is_reonnect) {
        let _this = this;
        this.reconnect_timer = setInterval(() => {
        //  console.log("执行重连222", _this, _this.reconnect_current);
          // 超过重连次数 清除定时器timer 不在进行重连
          if (_this.reconnect_current > _this.reconnect_count) {
            clearInterval(_this.reconnect_timer);
            // 释放对象
            _this.ws = null;
            return;
          }
          // 记录重连次数
          _this.reconnect_current++;

          _this.reconnect();
        }, this.reconnect_interval);
      }
    };

    this.ws.onmessage = (e, callback = null) => {
      var params = JSON.parse(e.data);
      console.log("webSocket message", params);
      if (callback) {
        callback(params);
      }
    };

    this.ws.onopen = (e) => {
      console.log(
        "webSocket open 连接成功",
        e,
        this.reconnect_current,
        this.ws
      );
     // 给服务端发送连接成功标识固定信息 看业务场景需要来定义
      if (this.reconnect_current == 0) {
        let data = {
          action: 1,
          message: null,
          receivers: [],
          sender: "2c4a004330c74102a5c30fea0e769d93",
        };

        this.sendMsg(data);
      }
      clearInterval(this.reconnect_timer);

      this.reconnect_current = 0;
      this.socket_open = true;
      this.is_reonnect = true;
      this.heartbeat();
    };

    this.ws.onerror = (e) => {
      console.log("webSocket error WebSocket连接发生错误", e);
    };
  }

  // 发送消息 this.ws.readyState == this.ws.OPEN这些你们打印一下实例的对象就知道为啥这样判断了
  sendMsg(data, callback = null) {
    //已开启
    if (this.ws.readyState == this.ws.OPEN) {
      // console.log("执行发送", data);
      this.ws.send(JSON.stringify(data));

      if (callback) {
        callback();
      }

      // 正在开启状态,则等待1s后重新调用  
    } else if (this.ws.readyState == this.ws.CONNECTING) {
      setTimeout(function () {
        this.ws.send(JSON.stringify(data), callback);
      }, 1000);

      // 未开启,则等待1s后重新调用
    } else {
      this.initSocket();

      setTimeout(function () {
        this.ws.send(JSON.stringify(data), callback);
      }, 1000);
    }
  }

  //   心跳
  heartbeat() {
    if (this.hearbeat_timer) {
      clearInterval(this.hearbeat_timer);
    }

    let _this = this;

    this.hearbeat_timer = setInterval(() => {
      var data = {
        kind: 0, //请求类型 kind 0 心跳包
        kindString: "heartBeat",
      };
      //   console.log("里面==》", _this, JSON.stringify(data));
      _this.sendMsg(data);
    }, this.hearbeat_interval);
  }

  // 重连
  reconnect() {
    // 状态标识判断
    if (this.ws && this.socket_open) {
      this.ws.close();
    }

    this.ws = null;
    console.log("执行重连===>", this);
    this.initSocket();
  }
  // 主动销毁
  destory() {
    clearInterval(this.hearbeat_interval);
    this.is_reonnect = false;
    this.ws.close();
    // 释放对象
    this.ws = null;
  }
}

大体先这样拉 大佬们不想写可以直接用 部分稍微优化一下就好了 后期我也会补充优化版本

### 实现 WebSocket 封装 为了简化 WebSocket 的开发流程并提高代码的可维护性和重用性,通常会创建一个 WebSocket 封装库。这种封装不仅限于简单的连接管理,还可能涉及消息处理、错误恢复机制等功能。 #### 创建自定义 WebSocket 封装库 以下是 Python 中基于 `websockets` 库的一个简单 WebSocket 客户端封装实例: ```python import asyncio import websockets class SimpleWebSocketClient: def __init__(self, uri): self.uri = uri self.connection = None async def connect(self): try: self.connection = await websockets.connect(self.uri) print(f"Connected to server at {self.uri}") except Exception as e: print(f"Failed to connect: {e}") async def send_message(self, message): if not self.connection or not self.connection.open: raise ConnectionError("Not connected.") await self.connection.send(message) async def receive_message(self): while True: try: response = await self.connection.recv() return response except websockets.ConnectionClosed: break async def close_connection(self): if self.connection and self.connection.open: await self.connection.close() async def main(): client = SimpleWebSocketClient('ws://localhost:8765') await client.connect() await client.send_message("Hello Server!") reply = await client.receive_message() print(f"Received from server: {reply}") await client.close_connection() if __name__ == "__main__": asyncio.run(main()) ``` 此代码展示了如何构建一个基本的 WebSocket 客户端类[^1],它能够执行连接服务器、发送和接收数据的操作,并妥善关闭连接。 对于更复杂的场景,比如需要支持多线程操作或是与其他框架集成,则建议考虑现有的成熟解决方案,如 Flask-SocketIO 提供了对 WebSockets 和 Socket.IO 协议的支持,在 Flask 应用中非常容易上手[^3]。 #### 使用现有 WebSocket 封装库 除了自行编写外,还有许多成熟的 WebSocket 封装库可供选择,这些库往往已经解决了大量实际应用中的难题,提供了丰富的特性集。例如: - **Flask-SocketIO**: 结合 Flask 框架使用的 WebSocket 扩展包,适用于构建实时网络应用程序。 - **AutobahnPython**: 支持 WAMP (Web Application Messaging Protocol) 的高级 WebSocket/WSGI/Twisted 库,适合复杂的企业级项目需求。 - **Tornado**: Tornado 是另一个流行的异步网络库,内置了对 WebSocket 的良好支持,非常适合高并发环境下的服务端编程。 综上所述,无论是自己动手还是借助第三方工具,都可以有效地完成 WebSocket 功能的封装工作,从而让开发者专注于业务逻辑本身而不是底层协议细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值