websocket的封装

功能:
自动重连(断开自动重连)

心跳保活(防止服务器踢下线)

消息重发(发送失败重试)

错误统一处理

在线 / 离线监听

消息订阅 / 派发(解耦)

可重入、单例模式

javascript 复制代码
class WebSocketClient {
  constructor(url) {
    // 基础配置
    this.url = url
    this.socket = null
    this.isConnected = false

    // 重连配置
    this.reconnectEnabled = true // 自动重连开关
    this.reconnectDelay = 3000   // 重连间隔 3s
    this.reconnectTimer = null   // 重连定时器

    // 心跳配置(防止服务器断开)
    this.heartbeatEnabled = true
    this.heartbeatMsg = 'ping' // 心跳消息
    this.heartbeatInterval = 5000 // 5秒一次心跳
    this.heartbeatTimer = null

    // 消息订阅器(不同页面接收不同消息)
    this.listeners = new Map()

    // 缓存未发送成功的消息
    this.msgQueue = []
  }

  // ========== 1. 建立连接 ==========
  connect() {
    // 防止重复创建
    if (this.socket && this.socket.readyState === 1) return

    this.socket = new WebSocket(this.url)

    // 连接成功
    this.socket.onopen = (e) => {
      console.log('✅ WebSocket 连接成功')
      this.isConnected = true
      this.startHeartbeat() // 启动心跳
      this.clearReconnect() // 清除重连
      this.sendCacheMsg()   // 发送缓存消息
    }

    // 接收消息
    this.socket.onmessage = (e) => {
      try {
        const data = JSON.parse(e.data)
        this.dispatch(data) // 分发给订阅者
      } catch (err) {
        this.dispatch(e.data)
      }
    }

    // 关闭连接
    this.socket.onclose = (e) => {
      console.log('❌ WebSocket 断开')
      this.isConnected = false
      this.stopHeartbeat()
      this.reconnect() // 自动重连
    }

    // 错误
    this.socket.onerror = (err) => {
      console.error('❗ WebSocket 异常', err)
      this.isConnected = false
      this.reconnect()
    }
  }

  // ========== 2. 自动重连 ==========
  reconnect() {
    if (!this.reconnectEnabled || this.reconnectTimer) return
    console.log(`🔄 ${this.reconnectDelay / 1000}秒后重连...`)

    this.reconnectTimer = setTimeout(() => {
      this.connect()
      this.reconnectTimer = null
    }, this.reconnectDelay)
  }

  clearReconnect() {
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer)
      this.reconnectTimer = null
    }
  }

  // ========== 3. 心跳保活(最重要!) ==========
  startHeartbeat() {
    if (!this.heartbeatEnabled) return
    this.stopHeartbeat()

    this.heartbeatTimer = setInterval(() => {
      if (this.isConnected) {
        this.send(this.heartbeatMsg)
      }
    }, this.heartbeatInterval)
  }

  stopHeartbeat() {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer)
      this.heartbeatTimer = null
    }
  }

  // ========== 4. 发送消息(支持缓存) ==========
  send(data) {
    if (!this.isConnected) {
      this.msgQueue.push(data) // 未连接 → 缓存
      return
    }

    try {
      const msg = typeof data === 'string' ? data : JSON.stringify(data)
      this.socket.send(msg)
    } catch (err) {
      console.error('发送失败', err)
      this.msgQueue.push(data)
    }
  }

  // 发送缓存消息
  sendCacheMsg() {
    while (this.msgQueue.length) {
      const msg = this.msgQueue.shift()
      this.send(msg)
    }
  }

  // ========== 5. 订阅/派发(解耦) ==========
  on(key, callback) {
    this.listeners.set(key, callback)
  }

  off(key) {
    this.listeners.delete(key)
  }

  dispatch(data) {
    this.listeners.forEach((cb) => cb(data))
  }

  // ========== 6. 手动关闭 ==========
  close() {
    this.reconnectEnabled = false // 关闭重连
    this.stopHeartbeat()
    this.clearReconnect()
    this.socket?.close()
    this.isConnected = false
  }
}

// 导出单例
export default new WebSocketClient('ws://localhost:8080/ws')

使用

javascript 复制代码
import ws from '@/utils/websocket'

// 1. 连接
ws.connect()

// 2. 监听消息
ws.on('message', (data) => {
  console.log('收到服务器消息:', data)
})

// 3. 发送消息
ws.send({ type: 'chat', content: '你好' })

// 4. 页面卸载关闭
onUnmounted(() => {
  ws.off('message')
})
相关推荐
益莱储中国4 分钟前
深度解析:RF 实验室从 5G迈向 6G 的过程中保持技术领先与设备升级的路径
开发语言·php
xhyu611 小时前
【学习笔记】图像质量评估方法 (5.生成图像是否符合用户要求)
笔记·学习·计算机视觉
benchmark_cc1 小时前
Python 量化系统如何设计统一的数据访问接口:从策略解耦到数据层架构
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
程序员老赵1 小时前
Docker 部署青龙面板:轻松搭建定时任务管理平台
前端·docker·开源
Swot1 小时前
Asciidoctor 公式数字下标错位问题:原因分析与解决方案
前端
Swot1 小时前
leo-editor 中将 Markdown 内容转成 asciidoc 格式
前端
const_qiu1 小时前
第四章 00:开篇 —— 从「会聊天」到「记得住、会干活、能协作」
java·开发语言·人工智能·python
小天源1 小时前
让访问数据可解释:IP 地球大屏、地区库更新与运行维护设计
网络·网络协议·tcp/ip
Wang's Blog1 小时前
Java 项目实战: 交友项目 - 个人资料管理的更新接口实现与坑
java·开发语言·交友
狒狒AI1 小时前
Remotion / GSAP+Three / HyperFrames / Skia 四栈实测:代码渲染知识视频的选栈方法(附开源技能)
前端·人工智能·aigc