用了那么多年的WebSocket尽然发现断线重连后不会收到消息

实现一个健壮的WebSocket连接管理器

在现代Web应用中,实时通信变得越来越重要。WebSocket作为一种全双工通信协议,为前端应用提供了强大的实时数据交互能力。本文将介绍如何实现一个功能完善的WebSocket连接管理器,包含自动重连、心跳检测等关键特性。

WebSocket管理器的核心功能

实现的useWebSocket函数提供了以下核心功能:

  1. 自动连接:初始化时自动建立WebSocket连接
  2. 事件监听:通过事件机制处理消息、连接状态变化
  3. 心跳检测:定期发送心跳包保持连接活跃
  4. 自动重连:连接断开时自动尝试重新连接
  5. 手动控制:提供手动关闭连接的接口

实现解析

初始化与连接建立

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();
相关推荐
IT_陈寒13 分钟前
Vite性能优化实战:5个被低估的配置让你的开发效率提升50%
前端·人工智能·后端
IT_陈寒15 分钟前
Java性能调优的7个被低估的技巧:从代码到JVM全链路优化
前端·人工智能·后端
掘金安东尼40 分钟前
前端周刊第439期(2025年11月3日–11月9日)
前端·javascript·vue.js
码农刚子1 小时前
ASP.NET Core Blazor进阶1:高级组件开发
前端·前端框架
道可到1 小时前
重新审视 JavaScript 中的异步循环
前端
起这个名字1 小时前
微前端应用通信使用和原理
前端·javascript·vue.js
QuantumLeap丶1 小时前
《uni-app跨平台开发完全指南》- 06 - 页面路由与导航
前端·vue.js·uni-app
CSharp精选营1 小时前
ASP.NET Core Blazor进阶1:高级组件开发
前端·.net core·blazor
用户90443816324601 小时前
AI 生成的 ES2024 代码 90% 有坑!3 个底层陷阱 + 避坑工具,项目 / 面试双救命
前端·面试
小p2 小时前
react学习6:受控组件
前端·react.js