对 websocket 进行封装 (心跳检测 断开重连 发送事件等等 支持断开重连后发送上次发送的最后一个事件)
代码封装:
// websocketService.js import { ref } from "vue"; const { DEV, VITE_APP_PUSH_WS } = import.meta.env; const { push_ws } = window.WEB_CONFIG; const baseWsUrl = DEV ? VITE_APP_PUSH_WS : push_ws; class WebSocketService { constructor(url) { this.url = url; this.socket = null; this.reconnectTimer = null; this.heartbeatTimer = null; this.socketStatus = false; this.reconnectInterval = 5000; // 重连间隔时间 this.heartbeatInterval = 30000; // 心跳间隔时间 this.websocketObj = ref(null); this.onOpenCallback = null; // 新增用于保存连接成功后的回调函数 this.eventListeners = {}; // 用于存储事件监听器 this.lastSentMessage = null; // 存储最后发送的消息 } initSocket(onOpenCallback) { this.socket = new WebSocket(this.url); this.socket.onopen = () => { clearInterval(this.reconnectTimer); this.socketStatus = true; this.startHeartbeat(); this.websocketObj.value = this.socket; if (onOpenCallback) { onOpenCallback(); } if (this.lastSentMessage) { this.sendMessage(this.lastSentMessage); // 重连后发送最后一条消息 } }; this.socket.onmessage = (event) => { const data = JSON.parse(event.data); const token = window.localStorage.getItem('token') || ''; if (!token) { this.closeSocket(); } if (this.eventListeners[data.event]) { this.eventListeners[data.event].forEach(callback => callback(data)); } }; this.socket.onclose = () => { this.handleSocketClose(); }; this.socket.onerror = () => { this.handleSocketError(); }; } startHeartbeat() { this.heartbeatTimer = setInterval(() => { this.socket.send(JSON.stringify({ event: "heartbeat" })); }, this.heartbeatInterval); } stopHeartbeat() { clearInterval(this.heartbeatTimer); } closeSocket() { this.stopHeartbeat(); this.socket.close(); } handleSocketClose() { console.log("WebSocket closed"); this.socketStatus = false; this.stopHeartbeat(); this.reconnect(); } handleSocketError() { console.log("WebSocket error"); this.socketStatus = false; this.stopHeartbeat(); this.reconnect(); } reconnect() { if (this.reconnectTimer) return; this.reconnectTimer = setInterval(() => { this.initSocket(this.onOpenCallback); }, this.reconnectInterval); } sendMessage(message) { this.lastSentMessage = message; // 存储最后发送的消息 if (this.socket && this.socket.readyState === WebSocket.OPEN) { this.socket.send(message); } else { console.error('WebSocket is not open. Ready state is: ' + (this.socket ? this.socket.readyState : 'N/A')); } } addEventListener(event, callback) { if (!this.eventListeners[event]) { this.eventListeners[event] = []; } this.eventListeners[event].push(callback); } removeEventListener(event, callback) { if (this.eventListeners[event]) { this.eventListeners[event] = this.eventListeners[event].filter(cb => cb !== callback); } } } const wsUrl = `${baseWsUrl}/ws/footballMsg`; const websocketService = new WebSocketService(wsUrl); export const newwebsocketObj = websocketService.websocketObj; export const initWebsocketObj = (onOpenCallback) => { websocketService.initSocket(onOpenCallback); }; export const sendMessage = (message) => { websocketService.sendMessage(message); }; export const closeWebsocket = () => { websocketService.closeSocket(); }; export const addEventListener = (event, callback) => { websocketService.addEventListener(event, callback); }; export const removeEventListener = (event, callback) => { websocketService.removeEventListener(event, callback); };
代码使用:
<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue';
import { initWebsocketObj, sendMessage, addEventListener, removeEventListener, websocketObj } from './websocketService.js';
const tableData = ref([]);
const standardMatchId = ref('match_id_example'); // 这是一个示例的 match_id,你可以从路由或其他地方获取
// 处理 WebSocket 消息的回调函数
const handleFootballMessageEvent = (data) => {
if (data.event === 'FootballMessageEvent') {
const { id = '' } = data.payload || {};
if (!tableData.value.length || !id.startsWith(standardMatchId.value)) return;
tableData.value.unshift(data.payload);
tableData.value = [...new Set(tableData.value.map(JSON.stringify))].map(
JSON.parse
);
}
};
onMounted(() => {
// 初始化 WebSocket
initWebsocketObj(() => {
// 连接成功后发送初始消息
const message = JSON.stringify({
event: "subMatch",
payload: { FootballMessageEvent: [standardMatchId.value] }
});
sendMessage(message);
});
// 添加事件监听器
addEventListener('FootballMessageEvent', handleFootballMessageEvent);
// 监听 tableData 的变化
watch(tableData, (newValue) => {
const standardMatchIds = newValue.map(item => item.standard_match_id + '');
const params = {
BetMarketEvent: standardMatchIds,
FootballEvent: standardMatchIds
};
const message = JSON.stringify({ event: "subMatch", payload: params });
sendMessage(message);
});
// 组件卸载时移除事件监听器
onUnmounted(() => {
removeEventListener('FootballMessageEvent', handleFootballMessageEvent);
websocketObj.value && websocketObj.value.close();
});
});
</script>
<template>
<div>
<table>
<thead>
<tr>
<th>Match ID</th>
<th>Event</th>
</tr>
</thead>
<tbody>
<tr v-for="item in tableData" :key="item.standard_match_id">
<td>{{ item.standard_match_id }}</td>
<td>{{ item.event }}</td>
</tr>
</tbody>
</table>
</div>
</template>
越努力越幸运

浙公网安备 33010602011771号