一個簡單的 vue3 的 websocket hook. 有以下基礎功能: 創建鏈接 失敗重連 發送心跳包 import { ref } from "vue"; export interface WS_CONFIG { url: string; // ws鏈接地址 sendData?: Record ...
一個簡單的 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,
};
}