封裝websocktHooks
import { ref, onMounted, onUnmounted } from 'vue';/*** webSocket的Hooks* @param {string} websocket鏈接地址* */
export function useWebSocket(url: string) {// 核心狀態 const data: Ref<any> = ref(null);//收到websocket返回的數據const socket: Ref<WebSocket | null> = ref(null);//收到websocket返回的數據const isConnected: Ref<boolean> = ref(false);//是否鏈接成功const reconnectTimer: Ref<NodeJS.Timeout | null> = ref(null);//定時器變量const heartbeatTimer: Ref<NodeJS.Timeout | null> = ref(null);//定時器變量const HEARTBEAT_INTERVAL = 30000; // 心跳時間 const RECONNECT_DELAY = 5000;//重連時間/*** 創建連接* */ const connect = () => {if (socket.value) {socket.value.close();}// 初始化 WebSocket(傳入 URL 和配置)socket.value = new WebSocket(url);// 連接成功 socket.value.onopen = () => {console.log('WebSocket 連接成功');isConnected.value = true;clearReconnectTimer();startHeartbeat();};// 接收消息 socket.value.onmessage = (event) => {try {data.value = JSON.parse(event.data);} catch (error) {console.error('消息解析失敗', error);data.value = event.data;}};// 連接關閉 socket.value.onclose = (event) => {console.log(`WebSocket 關閉(代碼:${event.code})`);isConnected.value = false;stopHeartbeat();startReconnectTimer();};// 連接錯誤socket.value.onerror = (error) => {console.error('WebSocket 錯誤', error);isConnected.value = false;};};/*** 發送消息* */const send = (message: any) => {if (isConnected.value && socket.value) {try {const sendData = typeof message === 'string' ? message : JSON.stringify(message);socket.value.send(sendData);} catch (error) {console.error('發送消息失敗', error);}}};/*** 心跳檢測* */const startHeartbeat = () => {stopHeartbeat();heartbeatTimer.value = setInterval(() => {if (isConnected.value && socket.value) {send({ type: 'heartbeat' });console.log('發送心跳包');}}, HEARTBEAT_INTERVAL);};/*** 停止心跳* */const stopHeartbeat = () => {if (heartbeatTimer.value) {clearInterval(heartbeatTimer.value);heartbeatTimer.value = null;}};/*** 啟動重連計時器* */const startReconnectTimer = () => {clearReconnectTimer();reconnectTimer.value = setTimeout(() => {console.log('嘗試重連...');connect();}, RECONNECT_DELAY);};/*** 清除重連計時器* */const clearReconnectTimer = () => {if (reconnectTimer.value) {clearTimeout(reconnectTimer.value);reconnectTimer.value = null;}};/*** 手動關閉連接* */const close = () => {if (socket.value) {socket.value.close(1000, '手動關閉');}stopHeartbeat();clearReconnectTimer();};// 組件掛載時連接onMounted(() => connect());// 組件卸載時徹底關閉onUnmounted(() => {close();});return {data,isConnected,send,connect,close};
}
使用
這樣就可以請求到websocket了,并且每過30秒發送心跳,來判斷連接是否正常,斷開連接后5秒重新連接,關閉連接需要調用close()方法