Skip to content

useReactiveWebsocket

创建响应式 WebSocket 连接(跨框架实现)

前置依赖

依赖参数

参数名类型说明
deps.WebSocketWebSocketConstructorWebSocket 构造函数
deps.setTimeouttypeof setTimeout定时器函数
deps.clearTimeouttypeof clearTimeout清除定时器函数

环境要求

  • 浏览器环境: 需要支持 WebSocket API
  • Node.js环境: 需要安装 ws
bash
npm install ws

函数签名

typescript
interface UseReactiveWebsocketDeps {
  WebSocket: WebSocketConstructor
  setTimeout: typeof setTimeout
  clearTimeout: typeof clearTimeout
}

interface UseReactiveWebsocketOptions {
  protocols?: string | string[]
  immediate?: boolean
  heartbeat?: number
  heartbeatMessage?: WebSocketMessage
  reconnect?: ReconnectOptions
  onConnected?: (ws: WebSocket) => void
  onDisconnected?: (ws: WebSocket, event: any) => void
  onError?: (ws: WebSocket, event: any) => void
  onMessage?: (ws: WebSocket, event: any) => void
}

interface ReconnectOptions {
  enabled?: boolean
  delay?: number
  maxRetries?: number
  retryDelayMultiplier?: number
}

interface ReactiveWebSocketState {
  status: WebSocketStatus
  data: any
  error: Error | null
  retryCount: number
  ws: WebSocket | null
}

interface ReactiveWebSocketReturn {
  state: ReactiveWebSocketState
  send: (data: WebSocketMessage) => boolean
  connect: () => void
  disconnect: (code?: number, reason?: string) => void
  subscribe: (listener: () => void) => () => void
  dispose: () => void
}

function useReactiveWebsocket(
  url: string,
  options?: UseReactiveWebsocketOptions,
  deps: UseReactiveWebsocketDeps
): ReactiveWebSocketReturn

参数

参数名类型必填说明
urlstringWebSocket 服务器地址
optionsUseReactiveWebsocketOptions配置选项
depsUseReactiveWebsocketDeps环境依赖

UseReactiveWebsocketOptions 选项

名称类型默认值说明
protocolsstring | string[][]WebSocket 子协议
immediatebooleantrue是否立即连接
heartbeatnumber0心跳检测间隔(毫秒),0 表示禁用
heartbeatMessageWebSocketMessage'ping'心跳消息内容
heartbeatTimeoutnumber5000心跳超时时间(毫秒),超过此时间未收到任何消息则判定连接断开
reconnectReconnectOptions-重连配置
onConnectedFunction-连接成功回调
onDisconnectedFunction-断开连接回调
onErrorFunction-错误回调
onMessageFunction-消息回调

ReconnectOptions 重连配置

名称类型默认值说明
enabledbooleantrue是否启用自动重连
delaynumber3000重连延迟(毫秒)
maxRetriesnumber5最大重连次数,0 表示无限重连
retryDelayMultipliernumber1.5重连延迟增长因子

返回值

类型说明
ReactiveWebSocketReturn响应式 WebSocket 对象

ReactiveWebSocketReturn 属性和方法

名称类型说明
stateReactiveWebSocketState响应式状态对象
send(data: WebSocketMessage) => boolean发送消息
connect() => void连接 WebSocket
disconnect(code?, reason?) => void断开连接
subscribe(listener: () => void) => () => void订阅状态变化
dispose() => void销毁实例

ReactiveWebSocketState 状态对象

名称类型说明
statusWebSocketStatus连接状态:CONNECTING / CONNECTED / DISCONNECTED / ERROR
dataany最新接收的数据
errorError | null错误信息
retryCountnumber当前重连次数
wsWebSocket | nullWebSocket 实例

工作原理

  1. 创建响应式状态对象,包含连接状态、接收数据、错误信息等
  2. 根据配置选项创建 WebSocket 连接
  3. 监听 WebSocket 事件(open、message、error、close)并更新响应式状态
  4. 支持自动重连,非正常断开时自动尝试重连,重连延迟递增
  5. 支持心跳检测和超时检测:
    • 定时发送心跳消息
    • 监控消息接收,如果超过 heartbeat + heartbeatTimeout 时间未收到任何消息
    • 自动关闭连接并触发重连机制
  6. 提供 send 方法发送消息,connect/disconnect 方法控制连接
  7. 通过 subscribe 方法监听状态变化
  8. 支持跨框架使用(不依赖 Vue 或其他框架)

心跳检测机制

心跳检测解决了网络断开但 WebSocket 不会立即触发 onclose 事件的问题:

  1. 每隔 heartbeat 毫秒发送一次心跳消息
  2. 同时设置超时检测:如果在 heartbeat + heartbeatTimeout 时间内没有收到任何消息
  3. 判定连接已断开,主动关闭 WebSocket
  4. 触发 onclose 事件,进入重连流程

这样即使是断网、服务器无响应等情况,也能及时发现并重连。

测试心跳超时

在 Playground 中测试时需要注意:

默认的 echo.websocket.org 服务器会响应所有消息,包括心跳 ping,所以不会触发超时。

要测试超时重连功能,可以:

  1. 使用本地 WebSocket 服务器:启动一个不响应心跳的 WebSocket 服务器
  2. 设置非常短的心跳间隔:设置 5 秒心跳 + 3 秒超时,然后断网观察
  3. 查看浏览器控制台日志:打开 DevTools 查看详细的心跳检测日志

日志示例:

[连接] 连接成功,记录时间: 1234567890
[连接] 启动心跳检测: 间隔=5000ms, 超时=3000ms
[心跳] 检查: 距上次消息 5001ms, 超时阈值 8000ms
[心跳] 发送心跳消息
[消息] 收到消息,更新时间: 1234567890 -> 1234572891  ← 收到响应
[心跳] 检查: 距上次消息 5002ms, 超时阈值 8000ms
[心跳] ⚠️ 检测到超时,关闭连接  ← 没收到响应
[关闭] 连接关闭: isTimeoutClose=true
[关闭] 是否重连: true