实现一个健壮的WebSocket连接管理器
在现代Web应用中,实时通信变得越来越重要。WebSocket作为一种全双工通信协议,为前端应用提供了强大的实时数据交互能力。本文将介绍如何实现一个功能完善的WebSocket连接管理器,包含自动重连、心跳检测等关键特性。
WebSocket管理器的核心功能
实现的useWebSocket
函数提供了以下核心功能:
- 自动连接:初始化时自动建立WebSocket连接
- 事件监听:通过事件机制处理消息、连接状态变化
- 心跳检测:定期发送心跳包保持连接活跃
- 自动重连:连接断开时自动尝试重新连接
- 手动控制:提供手动关闭连接的接口
实现解析
初始化与连接建立
js
// 生成 digits 位随机数
const randomNumber = (digits = 8) =>{
const min = Math.pow(10, digits - 1); // 10^(digits-1) 例如 8 位数最小是 10000000
const max = Math.pow(10, digits) - 1; // 10^digits - 1 例如 8 位数最大是 99999999
return Math.floor(Math.random() * (max - min + 1)) + min;
}
export const useWebSocket = ({url = null, content, time = 10, heartbeat = 10, protocols = null}) => {
const info = {
// 存储各种状态和配置
heartbeatInterval: null,
time: time || 10, // 重连间隔(秒)
heartbeat: heartbeat || 10, // 心跳间隔(秒)
TIMEID: null, // 重连定时器ID
socket: null, // WebSocket实例
protocols: protocols || null,
url: url || null,
content: content || 'ping',
eventTarget: new EventTarget(), // 事件系统
isManuallyClosed: false, // 是否手动关闭
isConnected: false // 连接状态
}
const initWebSocket = () => {
if (info.isManuallyClosed) return;
info.socket?.close();
info.socket = null;
const protocol = location.protocol === 'https' ? 'wss' : 'ws';
// 根据实际需求可以在后面拼接随机数
const adder = info.url || import.meta.env.VITE_SOKET_URL;
info.socket = info.protocols
? new WebSocket(`${protocol}://${adder}`, info.protocols)
: new WebSocket(`${protocol}://${adder}`);
setupEventHandlers();
}
}
事件处理
js
const setupEventHandlers = () => {
// 连接成功
info.socket.onopen = () => {
info.eventTarget.dispatchEvent(new CustomEvent('open', {detail: "onopen"}));
info.isConnected = true;
send(info.content);
startHeartbeat();
}
// 接收消息
info.socket.onmessage = (evt) => {
info.eventTarget.dispatchEvent(new CustomEvent('message', {detail: evt.data}));
}
// 连接关闭
info.socket.onclose = (e) => {
info.isConnected = false;
info.eventTarget.dispatchEvent(new CustomEvent('close', {detail: e}));
if (!info.isManuallyClosed) attemptReconnect();
}
// 连接错误
info.socket.onerror = (e) => {
info.isConnected = false;
info.eventTarget.dispatchEvent(new CustomEvent('error', {detail: e}));
attemptReconnect();
}
}
心跳机制
js
// 开始心跳检测
const startHeartbeat = () => {
stopHeartbeat();
info.heartbeatInterval = setInterval(
() => send(info.content),
info.heartbeat * 1000
);
}
// 停止心跳检测
const stopHeartbeat = () => {
clearInterval(info.heartbeatInterval);
info.heartbeatInterval = null;
};
自动重连机制
js
// 尝试重新连接
const attemptReconnect = () => {
stopHeartbeat();
clearTimeout(info.TIMEID);
info.TIMEID = setTimeout(initWebSocket, info.time * 1000);
}
公共API
js
return {
// 发送消息
send: (msg) => info.socket?.send(msg),
// 监听事件
on: (event, handler) => info.eventTarget?.addEventListener(event, handler),
// 关闭连接
close: (code = 1000, msg = '正常手动关闭') => {
info.isManuallyClosed = true;
clearTimeout(info.TIMEID);
stopHeartbeat();
info.socket?.close(code, msg);
info.socket = null;
info.isConnected = false;
removeEventListeners();
}
}
使用示例
js
// 创建WebSocket连接
const ws = useWebSocket({
url: '192.168.3.21:9001/websoket/user',
time: 5, // 5秒重连间隔
heartbeat: 15 // 15秒心跳间隔
});
// 监听消息
ws.on('message', (event) => {// 断线重连后收到消息依旧会触发
console.log('收到消息:', event.detail);
});
// 监听连接打开
ws.on('open', () => {
console.log('连接已建立');
});
// 监听连接关闭
ws.on('close', () => {
console.log('连接已关闭');
});
// 发送消息
ws.send('Hello WebSocket!');
// 手动关闭连接
ws.close();