react中使用webscoket,封装webscoket类。

webscoket

服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
(1)建立在 TCP 协议之上,服务器端的实现比较容易。

(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

(3)数据格式比较轻量,性能开销小,通信高效。

(4)可以发送文本,也可以发送二进制数据。

(5)没有同源限制,客户端可以与任意服务器通信。

(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

前端基础用法:

连接:

const ws = new Wenscoket('ws://xxxx')
这样就就会创建ws实例并且客户端就会与服务器进行连接。
ws.onopen=()=>{} //连接成功之后的监听
ws.onclose=()=>{} //连接失败或者关闭的回调
ws.onmessage=(data)=>{} //监听后端发送的信息
ws.onerror = ()=>{} //出错之后的回调。
ws.send(data)//向后端发送信息。

后端基本用法(node)

const WebSocket = require("ws");
const path = require("path");
const wss = new WebSocket.Server({. //新建实例
  port: 9998,
});


  wss.on("connection", (client) => { //开启服务
    client.on("message", async (msg) => { //监听前端的发送数据,msg为前端发送回来
        client.send(JSON.stringify(payload)); //向后端发送数据
        //所有客户端 wss.clients,向所有连接客户端发送数据
        wss.clients.forEach((item) => {
            item.send(msg);
        });
      }
    });
  });


前端封装类

interface WebSocketDataParams {
  socketType: string;
  action: string;
  chartName: string;
  value: boolean;
}
interface WebSocketDataProps {
  socketType: string;
  action: string;
  chartName: string;
  value: boolean;
  data: string;
}

class SocketService {
  /**
   * 单例 保证拿到的都是同一个实例
   */
  static instance: SocketService;
  static get Instance() {
    if (!this.instance) {
      this.instance = new SocketService();
    }
    return this.instance;
  }

  baseUrl: string;
  ws: WebSocket;
  callBackMapping: Record<string, any>;
  isconnect: boolean;
  sendRetryCount: number; //重复发送次数
  connectRetryCount: number;
  constructor(url: string = "ws://localhost:9998") {
    this.baseUrl = url;
    this.ws = {} as WebSocket;
    this.callBackMapping = {};
    this.isconnect = false;
    this.sendRetryCount = 0;
    this.connectRetryCount = 0;
  }

  //和服务端创建的stocket对象

  //定义连接服务器的方法
  connect(url = "") {
    if (!window.WebSocket) {
      return console.log("您的浏览器不支持WebSocket");
    }
    url = url ? url : this.baseUrl;
    this.ws = new WebSocket(url);

    //连接监听
    this.ws.onopen = () => {
      console.log("连接服务端成功");
      this.connectRetryCount = 0;
      this.isconnect = true;
    };

    this.ws.onclose = () => {
      this.connectRetryCount++;
      console.log("连接失败/关闭");
      this.isconnect = false;
      //当连接关闭后进行重新连接尝试
      setTimeout(() => {
        this.connect();
      }, this.connectRetryCount * 500);
    };

    this.ws.onmessage = (res) => {
      const recvData: WebSocketDataProps = JSON.parse(res.data);
      const stocketType = recvData.socketType; //与后端约定type
      //如果存在,直接调用
      const callBack = this.callBackMapping[stocketType]; //执行订阅的回调
      if (callBack) {
        const action = recvData.action;
        if (action === "getData") {
          const realData = JSON.parse(recvData.data);
          //将数据传给回调函数
          callBack.call(this, realData);
        } else if (action === "fullScreen") {
        } else if (action === "themeChange") {
        }
      }
    };
  }

  //注册回调函数,可能有多个scoket
  registerCallBack(
    socketType: string,
    callBack: (data: Record<string, any>) => void
  ) {
    this.callBackMapping[socketType] = callBack;
  }

  unRegisterCallBack(socketType: string) {
    this.callBackMapping[socketType] = null;
  }

  send(data: WebSocketDataParams) {
    if (this.isconnect) {
      this.sendRetryCount = 0; //发送成功重置为0
      this.ws.send(JSON.stringify(data));
    } else {
      setTimeout(() => {
        this.sendRetryCount++;
        this.send(data);
      }, this.sendRetryCount * 500);
    }
  }
}
const wss = SocketService.Instance;
export { wss };

采用封装类,然后可能会有多个页面需要使用到,所以采用派发订阅的模式
在这里插入图片描述
在这里插入图片描述
监听到数据的时候拿到对应的订阅函数执行。在这里插入图片描述
如,注册,然后记得注销掉。
这样一监听到后端返回来的数据就会执行回应的回调函数。

猜你喜欢

转载自blog.csdn.net/lin_fightin/article/details/121380700