一個簡單的websocket hook

一個簡單的 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,
  };
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章