|
|
@@ -5,6 +5,8 @@ import { useWebSocket, WebSocketResult } from '@vueuse/core';
|
|
|
import { getToken } from '/@/utils/auth';
|
|
|
|
|
|
let result: WebSocketResult<any>;
|
|
|
+// [perf-base-v1] S-W 6b: 记录当前连接的 url,供幂等判断(不同 url 需先断开再按新地址重连)
|
|
|
+let currentUrl = '';
|
|
|
const listeners = new Map();
|
|
|
|
|
|
/**
|
|
|
@@ -15,16 +17,33 @@ export function connectWebSocket(url: string) {
|
|
|
//update-begin-author:taoyan date:2022-4-24 for: v2.4.6 的 websocket 服务端,存在性能和安全问题。 #3278
|
|
|
const token = (getToken() || '') as string;
|
|
|
console.log(url);
|
|
|
- result = useWebSocket(url);
|
|
|
+ // [perf-base-v1] S-W 6b: 幂等化——同 url 且已 OPEN/CONNECTING 直接复用现有连接,避免重复 connect 造成多连接并存、消息重复分发
|
|
|
+ if (result) {
|
|
|
+ const status = unref(result.status);
|
|
|
+ if ((status === 'OPEN' || status === 'CONNECTING') && currentUrl === url) {
|
|
|
+ console.log('[WebSocket] 已存在活动连接,复用(status=' + status + ')');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // [perf-base-v1] S-W 6b: 不同 url 或旧连接已关闭:先真实 close 旧实例(6a 修复后 close 为 vueuse 原始方法)
|
|
|
+ try {
|
|
|
+ result.close();
|
|
|
+ } catch (e) {
|
|
|
+ console.warn('[WebSocket] 关闭旧连接异常(忽略):', e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ currentUrl = url;
|
|
|
+ // [perf-base-v1] S-W 6a: 不再覆写 vueuse 返回的 open/close 为日志函数(原写法导致 close() 无法真实断开连接),
|
|
|
+ // 日志移入 onConnected/onDisconnected 回调;onMessage/onError 改走 options 传入,重连后新实例依然生效
|
|
|
+ result = useWebSocket(url, {
|
|
|
+ onConnected: () => onOpen(),
|
|
|
+ onDisconnected: (_ws, e) => onClose(e),
|
|
|
+ onError: (_ws, e) => onError(e),
|
|
|
+ onMessage: (_ws, e) => onMessage(e),
|
|
|
+ });
|
|
|
//update-end-author:taoyan date:2022-4-24 for: v2.4.6 的 websocket 服务端,存在性能和安全问题。 #3278
|
|
|
if (result) {
|
|
|
- result.open = onOpen;
|
|
|
- result.close = onClose;
|
|
|
-
|
|
|
const ws = unref(result.ws);
|
|
|
if (ws != null) {
|
|
|
- ws.onerror = onError;
|
|
|
- ws.onmessage = onMessage;
|
|
|
console.log('WebSocket连接通了', result, ws);
|
|
|
} else {
|
|
|
console.log('WebSocket连接连接失败');
|