hotgo/web/src/utils/websocket/index.ts
孟帅 dc20a86b33 fix 修复websocket在某些情况下不重连问题
fix 修复登录日志查看权限
feat 访问日志增加接口信息显示
perf 为所有orm的Insert操作增加OmitEmptyData选项
2024-04-24 23:29:50 +08:00

189 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { SocketEnum } from '@/enums/socketEnum';
import { useUserStoreWidthOut } from '@/store/modules/user';
import { isJsonString } from '@/utils/is';
import { registerGlobalMessage } from '@/utils/websocket/registerMessage';
// WebSocket消息格式
export interface WebSocketMessage {
event: string;
data: any;
code: number;
timestamp: number;
}
let socket: WebSocket;
let isActive: boolean;
const messageHandler: Map<string, Function> = new Map();
export default () => {
const heartCheck = {
timeout: 5000,
timeoutObj: setTimeout(() => {}),
serverTimeoutObj: setInterval(() => {}),
reset: function () {
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
return this;
},
start: function () {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this;
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
this.timeoutObj = setTimeout(function () {
socket.send(
JSON.stringify({
event: SocketEnum.EventPing,
})
);
self.serverTimeoutObj = setTimeout(function () {
console.log('[WebSocket] 关闭服务');
socket.close();
}, self.timeout);
}, this.timeout);
},
};
const useUserStore = useUserStoreWidthOut();
let lockReconnect = false;
let timer: ReturnType<typeof setTimeout>;
const createSocket = () => {
console.log('[WebSocket] createSocket...');
if (useUserStore.token === '' || useUserStore.config?.wsAddr == '') {
console.error('[WebSocket] 用户未登录,稍后重试...');
resetReconnect();
return;
}
try {
socket = new WebSocket(`${useUserStore.config?.wsAddr}?authorization=${useUserStore.token}`);
init();
if (lockReconnect) {
lockReconnect = false;
}
} catch (e) {
console.error(`[WebSocket] createSocket err: ${e}`);
resetReconnect();
return;
}
};
const resetReconnect = () => {
if (lockReconnect) {
lockReconnect = false;
}
reconnect();
};
const reconnect = () => {
console.log('[WebSocket] lockReconnect:' + lockReconnect);
if (lockReconnect) return;
lockReconnect = true;
clearTimeout(timer);
timer = setTimeout(() => {
createSocket();
}, 2000);
};
const init = () => {
socket.onopen = function (_) {
console.log('[WebSocket] 已连接');
heartCheck.reset().start();
isActive = true;
};
socket.onmessage = function (event) {
isActive = true;
// console.log('WebSocket:收到一条消息', event.data);
if (!isJsonString(event.data)) {
console.log('[WebSocket] message incorrect format:' + JSON.stringify(event));
return;
}
heartCheck.reset().start();
const message = JSON.parse(event.data) as WebSocketMessage;
onMessage(message);
};
socket.onerror = function (_) {
console.log('[WebSocket] 发生错误');
reconnect();
isActive = false;
};
socket.onclose = function (_) {
console.log('[WebSocket] 已关闭');
heartCheck.reset();
reconnect();
isActive = false;
};
window.onbeforeunload = function () {
socket.close();
isActive = false;
};
};
createSocket();
registerGlobalMessage();
};
function onMessage(message: WebSocketMessage) {
let handled = false;
messageHandler.forEach((value: Function, key: string) => {
if (message.event === key || key === '*') {
handled = true;
value.call(null, message);
}
});
if (!handled) {
console.log('[WebSocket] messageHandler not registered. message:' + JSON.stringify(message));
}
}
// 发送消息
export function sendMsg(event: string, data: any = null, isRetry = true) {
if (socket === undefined || !isActive) {
if (!isRetry) {
console.log('[WebSocket] 连接异常,发送失败!');
return;
}
console.log('[WebSocket] 连接异常,等待重试..');
setTimeout(() => {
sendMsg(event, data);
}, 200);
return;
}
try {
socket.send(JSON.stringify({ event, data }));
} catch (err: any) {
console.log('[WebSocket] 发送消息失败err', err.message);
if (!isRetry) {
return;
}
console.log('[WebSocket] 等待重试..');
setTimeout(() => {
sendMsg(event, data);
}, 100);
}
}
// 添加消息处理
export function addOnMessage(key: string, value: Function): void {
messageHandler.set(key, value);
}
// 移除消息处理
export function removeOnMessage(key: string): boolean {
return messageHandler.delete(key);
}
// 查看所有消息处理
export function getAllOnMessage(): Map<string, Function> {
return messageHandler;
}