vue3中对websoket的二次封装,拿来即用

封装的重点是响应式状态管理、自动重连、心跳检测、消息队列、生命周期管理和易用性。通过Composition API将这些功能模块化,方便在Vue3组件中复用。

1、在 Vue3 中对 WebSocket 进行封装时,可以利用 Composition API 实现更优雅的封装。下面是一个功能完善且支持自动重连、心跳检测的 WebSocket 封装方案:

import { ref, reactive, onUnmounted } from 'vue'

interface WebSocketOptions {
  // 自动重连次数(默认 3 次)
  reconnectLimit?: number
  // 重连间隔(默认 3000ms)
  reconnectInterval?: number
  // 心跳间隔(默认 30000ms)
  heartInterval?: number
  // 心跳消息(默认 ping)
  heartMessage?: string
  // 是否自动连接(默认 true)
  autoConnect?: boolean
  // 协议字符串或字符串数组
  protocols?: string | string[]
}

export function useWebSocket(url: string, options: WebSocketOptions = {}) {
  const {
    reconnectLimit = 3,
    reconnectInterval = 3000,
    heartInterval = 30000,
    heartMessage = 'ping',
    autoConnect = true,
    protocols = []
  } = options

  // 响应式状态
  const ws = ref<WebSocket | null>(null)
  const isConnected = ref(false)
  const messageQueue = reactive<any[]>([])
  const reconnectCount = ref(0)
  const timer = ref<number>()
  const heartTimer = ref<number>()

  // 事件处理器
  const handlers = reactive<{
    message: ((event: MessageEvent) => void)[]
    open: ((event: Event) => void)[]
    close: ((event: CloseEvent) => void)[]
    error: ((event: Event) => void)[]
  }>({
    message: [],
    open: [],
    close: [],
    error: []
  })

  // 心跳检测
  const heartCheck = () => {
    heartTimer.value = window.setInterval(() => {
      send(heartMessage)
    }, heartInterval)
  }

  // 清除心跳
  const clearHeartCheck = () => {
    heartTimer.value && clearInterval(heartTimer.value)
  }

  // 发送消息
  const send = (data: string | ArrayBuffer | Blob) => {
    if (isConnected.value && ws.value) {
      ws.value.send(data)
    } else {
      messageQueue.push(data)
    }
  }

  // 处理队列消息
  const processMessageQueue = () => {
    while (messageQueue.length > 0 && ws.value) {
      const message = messageQueue.shift()
      ws.value.send(message)
    }
  }

  // 关闭连接
  const close = () => {
    ws.value?.close()
  }

  // 创建连接
  const connect = () => {
    ws.value = new WebSocket(url, protocols)
    
    ws.value.onopen = (event) => {
      isConnected.value = true
      reconnectCount.value = 0
      processMessageQueue()
      heartCheck()
      handlers.open.forEach(handler => handler(event))
    }

    ws.value.onmessage = (event) => {
      handlers.message.forEach(handler => handler(event))
    }

    ws.value.onclose = (event) => {
      isConnected.value = false
      clearHeartCheck()
      handlers.close.forEach(handler => handler(event))
      if (reconnectCount.value < reconnectLimit) {
        timer.value = window.setTimeout(() => {
          reconnectCount.value++
          connect()
        }, reconnectInterval)
      }
    }

    ws.value.onerror = (event) => {
      isConnected.value = false
      clearHeartCheck()
      handlers.error.forEach(handler => handler(event))
      ws.value?.close()
    }
  }

  // 自动连接
  if (autoConnect) {
    connect()
  }

  // 组件卸载时清理
  onUnmounted(() => {
    close()
    timer.value && clearTimeout(timer.value)
    clearHeartCheck()
  })

  return {
    ws,
    isConnected,
    send,
    close,
    connect,
    messageQueue,
    onMessage: (handler: (event: MessageEvent) => void) => {
      handlers.message.push(handler)
    },
    onOpen: (handler: (event: Event) => void) => {
      handlers.open.push(handler)
    },
    onClose: (handler: (event: CloseEvent) => void) => {
      handlers.close.push(handler)
    },
    onError: (handler: (event: Event) => void) => {
      handlers.error.push(handler)
    }
  }
}

2、使用示例

<script setup lang="ts">
import { useWebSocket } from './useWebSocket'

const {
  isConnected,
  send,
  onMessage,
  onOpen,
  onClose
} = useWebSocket('wss://echo.websocket.org', {
  heartInterval: 15000,
  reconnectLimit: 5
})

onOpen(() => {
  console.log('连接已建立')
  send('Hello Server!')
})

onMessage((event) => {
  console.log('收到消息:', event.data)
})

onClose(() => {
  console.log('连接已关闭')
})
</script>

<template>
  <div>
    <p>连接状态: {{ isConnected ? '已连接' : '未连接' }}</p>
    <button @click="send('ping')">发送心跳</button>
  </div>
</template>

3、功能总结:

主要功能特性

  1. 自动重连机制

    • 当连接意外断开时自动尝试重连

    • 可配置最大重连次数和重连间隔

    • 重连次数计数器自动重置

  2. 心跳检测

    • 定期发送心跳消息保持连接

    • 可自定义心跳间隔和消息内容

    • 自动清除心跳定时器

  3. 消息队列管理

    • 在连接建立前缓存待发送消息

    • 连接成功后自动发送队列消息

    • 支持字符串、ArrayBuffer 和 Blob 格式

  4. 事件监听

    • 提供 open、message、close、error 事件订阅

    • 支持多个事件处理器

    • 自动清理事件监听

  5. 响应式状态

    • 使用 ref 和 reactive 管理连接状态

    • 自动更新连接状态(isConnected)

    • 消息队列响应式更新

  6. 生命周期管理

    • 组件卸载时自动关闭连接

    • 自动清理定时器和心跳检测

    • 防止内存泄漏

  7. 灵活配置

    • 支持自定义协议

    • 可配置是否自动连接

    • 参数类型严格校验

注意事项

  1. 需要根据业务需求适当调整心跳间隔

  2. 重连次数不宜设置过大(建议 3-5 次)

  3. 建议配合 JSON 格式使用消息内容

  4. 生产环境需要处理 WebSocket 安全策略

  5. 对于敏感操作建议添加认证机制

  6. 可扩展添加消息序列化/反序列化逻辑

这个封装方案提供了 WebSocket 的核心功能实现,可以根据具体业务需求进行扩展,例如添加消息类型验证、请求响应匹配、二进制数据处理等功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值