发布时间:2022-08-13 文章分类:编程知识 投稿人:王小丽 字号: 默认 | | 超大 打印

一个简单的 vue3 的 websocket hook. 有以下基础功能:

import { ref } from "vue";
export interface WS_CONFIG {
  url: string; // ws链接地址
  sendData?: Record<string, any>; // 请求数据
  reconnectSec?: number; // 请求异常重连间隔
  needHeart?: boolean; // 是否需要心跳
  heartSec?: number; // 心跳间隔
  heartData?: unknown; // 心跳时发送的数据
}
export default function <T>({
  url,
  sendData = {},
  heartSec = 1000 * 30,
  needHeart = false,
  reconnectSec = 1000 * 30,
  heartData = "ping",
}: WS_CONFIG) {
  // 响应数据
  const wsData = ref<T | undefined>();
  // 重试次数
  const retryNumber = ref<number>(0);
  let socket: WebSocket | null = null;
  let heart_Interval: number | null = null;
  let lockConnect = false;
  let number = 0;
  // 创建链接
  function connect() {
    // 重连之前,关闭上次的连接
    if (socket) {
      socket.close();
    }
    socket = new WebSocket(url);
    retryNumber.value = number++;
    // 连接成功回调
    socket.onopen = () => {
      console.log(`${url} open event - ${new Date()}`);
      // 维持心跳
      needHeart && heart();
      // 清空重试次数
      number = 0;
      retryNumber.value = 0;
      // 发送数据
      socket?.send(JSON.stringify(sendData));
    };
    // 连接断开回调
    socket.onclose = (e) => {
      console.log(`
${new Date()}
${url} close event
code: ${e.code};
reason: ${e.reason};
isTrusted: ${e.isTrusted};
        `);
      console.log(`reconnect - ${new Date()}`);
      // 进行重连
      reconnect();
    };
    // 连接失败回调
    socket.onerror = (e) => {
      console.log(`${url} error event`, e);
      // 进行重连
      reconnect();
    };
    // 接收到数据
    socket.onmessage = (e: MessageEvent<string>) => {
      const { data } = e;
      const _data = (typeof data === "string" ? JSON.parse(data) : data) as T;
      wsData.value = _data;
    };
  }
  // 心跳函数,维持链接不断开
  function heart() {
    clearHeart();
    heart_Interval = setInterval(() => {
      socket?.send(
        typeof heartData === "string" ? heartData : JSON.stringify(heartData)
      );
    }, heartSec);
  }
  // 断开心跳
  function clearHeart() {
    heart_Interval && clearInterval(heart_Interval);
  }
  // 重连
  function reconnect() {
    // 控制重连频率
    if (lockConnect) {
      return;
    }
    lockConnect = true;
    // 清除心跳
    clearHeart();
    setTimeout(() => {
      lockConnect = false;
      connect();
    }, reconnectSec);
  }
  connect();
  // 关闭链接
  function clearWS() {
    socket?.close();
    clearHeart();
  }
  return {
    wsData,
    retryNumber,
    clearWS,
  };
}