refactor: ♻️ 添加 websocket 开启控制,未配置 endpoint 不连接,单例控制 websocket 重复连接

This commit is contained in:
Ray.Hao
2025-04-29 23:37:13 +08:00
parent ea6323084c
commit 142d808a5e
4 changed files with 46 additions and 17 deletions

View File

@@ -28,14 +28,13 @@ export interface UseStompOptions {
export function useStomp(options: UseStompOptions = {}) { export function useStomp(options: UseStompOptions = {}) {
// 默认值brokerURL 从环境变量中获取token 从 getAccessToken() 获取 // 默认值brokerURL 从环境变量中获取token 从 getAccessToken() 获取
const defaultBrokerURL = import.meta.env.VITE_APP_WS_ENDPOINT || ""; const defaultBrokerURL = import.meta.env.VITE_APP_WS_ENDPOINT || "";
// 不再使用defaultToken每次连接时直接获取最新token
const brokerURL = ref(options.brokerURL ?? defaultBrokerURL); const brokerURL = ref(options.brokerURL ?? defaultBrokerURL);
// 不再存储token改为在初始化时获取 // 默认配置参数
const reconnectDelay = options.reconnectDelay ?? 8000; const reconnectDelay = options.reconnectDelay ?? 15000; // 默认15秒重连间隔
const connectionTimeout = options.connectionTimeout ?? 10000; const connectionTimeout = options.connectionTimeout ?? 10000;
const useExponentialBackoff = options.useExponentialBackoff ?? false; const useExponentialBackoff = options.useExponentialBackoff ?? false;
const maxReconnectAttempts = options.maxReconnectAttempts ?? 5; const maxReconnectAttempts = options.maxReconnectAttempts ?? 3; // 最多重连3次
const maxReconnectDelay = options.maxReconnectDelay ?? 60000; const maxReconnectDelay = options.maxReconnectDelay ?? 60000;
// 连接状态标记 // 连接状态标记
@@ -76,7 +75,7 @@ export function useStomp(options: UseStompOptions = {}) {
Authorization: `Bearer ${currentToken}`, Authorization: `Bearer ${currentToken}`,
}, },
debug: options.debug ? console.log : () => {}, debug: options.debug ? console.log : () => {},
reconnectDelay: useExponentialBackoff ? 0 : reconnectDelay, // 使用自定义退避策略时禁用内置重连 reconnectDelay: useExponentialBackoff ? 0 : reconnectDelay, // 禁用内置重连机制
heartbeatIncoming: 4000, heartbeatIncoming: 4000,
heartbeatOutgoing: 4000, heartbeatOutgoing: 4000,
}); });
@@ -195,12 +194,19 @@ export function useStomp(options: UseStompOptions = {}) {
initializeClient(); initializeClient();
} }
if (client.value && (client.value.connected || client.value.active)) { if (!client.value) {
console.error("STOMP客户端初始化失败");
return; return;
} }
if (!client.value) { // 避免重复连接:检查是否已连接或正在连接
console.error("STOMP客户端初始化失败"); if (client.value.connected) {
console.log("WebSocket已经连接,跳过重复连接");
return;
}
if (client.value.active) {
console.log("WebSocket连接正在进行中,跳过重复连接请求");
return; return;
} }

View File

@@ -24,9 +24,10 @@ function createDictSyncHook() {
// 使用现有的useStomp配置适合字典场景的重连参数 // 使用现有的useStomp配置适合字典场景的重连参数
const { isConnected, connect, subscribe, unsubscribe, disconnect } = useStomp({ const { isConnected, connect, subscribe, unsubscribe, disconnect } = useStomp({
reconnectDelay: 10000, // 使用更长的重连延迟 - 10秒 reconnectDelay: 20000, // 字典更新重连时间
connectionTimeout: 15000, // 更长的连接超时时间 - 15秒 connectionTimeout: 15000, // 连接超时阈值
useExponentialBackoff: false, // 字典数据不需要指数退避策略 useExponentialBackoff: false, // 使用固定间隔重连策略
maxReconnectAttempts: 3, // 最多重连3次
}); });
// 存储订阅ID // 存储订阅ID
@@ -101,8 +102,8 @@ function createDictSyncHook() {
const attemptSubscribe = () => { const attemptSubscribe = () => {
if (!isConnected.value) { if (!isConnected.value) {
console.log("等待WebSocket连接建立..."); console.log("等待WebSocket连接建立...");
// 3秒后再次尝试 // 10秒后再次尝试
setTimeout(attemptSubscribe, 3000); setTimeout(attemptSubscribe, 10000);
return; return;
} }

View File

@@ -28,9 +28,9 @@ export function useOnlineCount() {
disconnect, disconnect,
isConnected: stompConnected, isConnected: stompConnected,
} = useStomp({ } = useStomp({
reconnectDelay: 5000, // 初始重连延迟5秒 reconnectDelay: 15000, // 重连基础延迟
maxReconnectAttempts: 3, // 最大重连3次 maxReconnectAttempts: 3, // 重连次数上限
connectionTimeout: 10000, // 连接超时10秒 connectionTimeout: 10000, // 连接超时
useExponentialBackoff: true, // 启用指数退避 useExponentialBackoff: true, // 启用指数退避
}); });
@@ -56,7 +56,11 @@ export function useOnlineCount() {
* 订阅在线用户计数主题 * 订阅在线用户计数主题
*/ */
const subscribeToOnlineCount = () => { const subscribeToOnlineCount = () => {
if (!stompConnected.value) return; if (!stompConnected.value) {
// 10秒后重试订阅
setTimeout(subscribeToOnlineCount, 10000);
return;
}
// 如果已经订阅,先取消订阅 // 如果已经订阅,先取消订阅
if (subscriptionId) { if (subscriptionId) {

View File

@@ -1,12 +1,28 @@
import { useDictSync } from "@/hooks/websocket/services/useDictSync"; import { useDictSync } from "@/hooks/websocket/services/useDictSync";
import { getAccessToken } from "@/utils/auth"; import { getAccessToken } from "@/utils/auth";
// 用于防止重复初始化的状态标记
let isInitialized = false;
/** /**
* 初始化WebSocket服务 * 初始化WebSocket服务
*/ */
export function setupWebSocket() { export function setupWebSocket() {
console.log("[WebSocketPlugin] 开始初始化WebSocket服务..."); console.log("[WebSocketPlugin] 开始初始化WebSocket服务...");
// 检查是否已经初始化
if (isInitialized) {
console.log("[WebSocketPlugin] WebSocket服务已经初始化,跳过重复初始化");
return;
}
// 检查环境变量是否配置
const wsEndpoint = import.meta.env.VITE_APP_WS_ENDPOINT;
if (!wsEndpoint) {
console.log("[WebSocketPlugin] 未配置WebSocket端点,跳过WebSocket初始化");
return;
}
// 检查token是否存在 // 检查token是否存在
const token = getAccessToken(); const token = getAccessToken();
if (!token) { if (!token) {
@@ -29,9 +45,11 @@ export function setupWebSocket() {
window.addEventListener("beforeunload", () => { window.addEventListener("beforeunload", () => {
console.log("[WebSocketPlugin] 窗口即将关闭断开WebSocket连接"); console.log("[WebSocketPlugin] 窗口即将关闭断开WebSocket连接");
dictWebSocket.closeWebSocket(); dictWebSocket.closeWebSocket();
isInitialized = false;
}); });
console.log("[WebSocketPlugin] WebSocket服务初始化完成"); console.log("[WebSocketPlugin] WebSocket服务初始化完成");
isInitialized = true;
}, 1000); // 延迟1秒初始化 }, 1000); // 延迟1秒初始化
} catch (error) { } catch (error) {
console.error("[WebSocketPlugin] 初始化WebSocket服务失败:", error); console.error("[WebSocketPlugin] 初始化WebSocket服务失败:", error);