97 lines
2.5 KiB
TypeScript
97 lines
2.5 KiB
TypeScript
import emitter from '@/utils/mitt';
|
||
|
||
type WebSocketInternalOptions = {
|
||
fullUrl: string;
|
||
reconnectInterval?: number;
|
||
};
|
||
|
||
let websocket: WebSocket | null = null;
|
||
let reconnectTimer: any = null;
|
||
let isManualClose = false;
|
||
|
||
/** 初始化WebSocket */
|
||
export function initWebSocket(options: WebSocketInternalOptions) {
|
||
const { fullUrl, reconnectInterval = 3000 } = options;
|
||
|
||
// 关闭已有连接
|
||
if (websocket) {
|
||
websocket.close();
|
||
}
|
||
|
||
if (!('WebSocket' in window)) {
|
||
console.error('当前浏览器不支持WebSocket');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
websocket = new WebSocket(fullUrl);
|
||
|
||
// 连接成功
|
||
websocket.onopen = () => {
|
||
clearTimeout(reconnectTimer!);
|
||
isManualClose = false;
|
||
console.log('WebSocket 连接成功');
|
||
};
|
||
|
||
// 接收消息,自动解析按 msgType 分发事件
|
||
websocket.onmessage = (event) => {
|
||
try {
|
||
const rawMsg = JSON.parse(event.data);
|
||
const msgType = rawMsg.msgType;
|
||
emitter.emit(msgType, rawMsg);
|
||
} catch (err) {
|
||
console.error('WebSocket消息解析失败:', err);
|
||
}
|
||
};
|
||
|
||
// 连接异常
|
||
websocket.onerror = (error) => {
|
||
console.error('WebSocket 连接异常:', error);
|
||
startReconnect(() => initWebSocket(options), reconnectInterval);
|
||
};
|
||
|
||
// 连接关闭
|
||
websocket.onclose = () => {
|
||
console.log('WebSocket 连接关闭');
|
||
if (!isManualClose) {
|
||
startReconnect(() => initWebSocket(options), reconnectInterval);
|
||
}
|
||
};
|
||
} catch (error) {
|
||
console.error('WebSocket 创建失败:', error);
|
||
startReconnect(() => initWebSocket(options), reconnectInterval);
|
||
}
|
||
}
|
||
|
||
/** 发送ws消息 */
|
||
export function sendWebSocketMessage(message: any): boolean {
|
||
if (websocket && websocket.readyState === WebSocket.OPEN) {
|
||
websocket.send(JSON.stringify(message));
|
||
return true;
|
||
}
|
||
console.error('WebSocket未连接,发送失败');
|
||
return false;
|
||
}
|
||
|
||
/** 手动关闭ws(登出时调用) */
|
||
export function closeWebSocket(): void {
|
||
isManualClose = true;
|
||
if (reconnectTimer) {
|
||
clearTimeout(reconnectTimer);
|
||
}
|
||
websocket?.close();
|
||
websocket = null;
|
||
}
|
||
|
||
/** 获取当前连接状态 */
|
||
export function getWebSocketState(): number | null {
|
||
return websocket?.readyState || null;
|
||
}
|
||
|
||
// 内部重连私有方法
|
||
function startReconnect(connectCallback: () => void, interval: number): void {
|
||
if (reconnectTimer) {
|
||
clearTimeout(reconnectTimer);
|
||
}
|
||
reconnectTimer = setTimeout(connectCallback, interval);
|
||
} |