useReactiveWebsocket
创建响应式 WebSocket 连接(跨框架实现)
前置依赖
依赖参数
| 参数名 | 类型 | 说明 |
|---|---|---|
deps.WebSocket | WebSocketConstructor | WebSocket 构造函数 |
deps.setTimeout | typeof setTimeout | 定时器函数 |
deps.clearTimeout | typeof 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参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
url | string | 是 | WebSocket 服务器地址 |
options | UseReactiveWebsocketOptions | 否 | 配置选项 |
deps | UseReactiveWebsocketDeps | 是 | 环境依赖 |
UseReactiveWebsocketOptions 选项
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
protocols | string | string[] | [] | WebSocket 子协议 |
immediate | boolean | true | 是否立即连接 |
heartbeat | number | 0 | 心跳检测间隔(毫秒),0 表示禁用 |
heartbeatMessage | WebSocketMessage | 'ping' | 心跳消息内容 |
heartbeatTimeout | number | 5000 | 心跳超时时间(毫秒),超过此时间未收到任何消息则判定连接断开 |
reconnect | ReconnectOptions | - | 重连配置 |
onConnected | Function | - | 连接成功回调 |
onDisconnected | Function | - | 断开连接回调 |
onError | Function | - | 错误回调 |
onMessage | Function | - | 消息回调 |
ReconnectOptions 重连配置
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled | boolean | true | 是否启用自动重连 |
delay | number | 3000 | 重连延迟(毫秒) |
maxRetries | number | 5 | 最大重连次数,0 表示无限重连 |
retryDelayMultiplier | number | 1.5 | 重连延迟增长因子 |
返回值
| 类型 | 说明 |
|---|---|
ReactiveWebSocketReturn | 响应式 WebSocket 对象 |
ReactiveWebSocketReturn 属性和方法
| 名称 | 类型 | 说明 |
|---|---|---|
state | ReactiveWebSocketState | 响应式状态对象 |
send | (data: WebSocketMessage) => boolean | 发送消息 |
connect | () => void | 连接 WebSocket |
disconnect | (code?, reason?) => void | 断开连接 |
subscribe | (listener: () => void) => () => void | 订阅状态变化 |
dispose | () => void | 销毁实例 |
ReactiveWebSocketState 状态对象
| 名称 | 类型 | 说明 |
|---|---|---|
status | WebSocketStatus | 连接状态:CONNECTING / CONNECTED / DISCONNECTED / ERROR |
data | any | 最新接收的数据 |
error | Error | null | 错误信息 |
retryCount | number | 当前重连次数 |
ws | WebSocket | null | WebSocket 实例 |
工作原理
- 创建响应式状态对象,包含连接状态、接收数据、错误信息等
- 根据配置选项创建 WebSocket 连接
- 监听 WebSocket 事件(open、message、error、close)并更新响应式状态
- 支持自动重连,非正常断开时自动尝试重连,重连延迟递增
- 支持心跳检测和超时检测:
- 定时发送心跳消息
- 监控消息接收,如果超过
heartbeat + heartbeatTimeout时间未收到任何消息 - 自动关闭连接并触发重连机制
- 提供 send 方法发送消息,connect/disconnect 方法控制连接
- 通过 subscribe 方法监听状态变化
- 支持跨框架使用(不依赖 Vue 或其他框架)
心跳检测机制
心跳检测解决了网络断开但 WebSocket 不会立即触发 onclose 事件的问题:
- 每隔
heartbeat毫秒发送一次心跳消息 - 同时设置超时检测:如果在
heartbeat + heartbeatTimeout时间内没有收到任何消息 - 判定连接已断开,主动关闭 WebSocket
- 触发
onclose事件,进入重连流程
这样即使是断网、服务器无响应等情况,也能及时发现并重连。
测试心跳超时
在 Playground 中测试时需要注意:
默认的 echo.websocket.org 服务器会响应所有消息,包括心跳 ping,所以不会触发超时。
要测试超时重连功能,可以:
- 使用本地 WebSocket 服务器:启动一个不响应心跳的 WebSocket 服务器
- 设置非常短的心跳间隔:设置 5 秒心跳 + 3 秒超时,然后断网观察
- 查看浏览器控制台日志:打开 DevTools 查看详细的心跳检测日志
日志示例:
[连接] 连接成功,记录时间: 1234567890
[连接] 启动心跳检测: 间隔=5000ms, 超时=3000ms
[心跳] 检查: 距上次消息 5001ms, 超时阈值 8000ms
[心跳] 发送心跳消息
[消息] 收到消息,更新时间: 1234567890 -> 1234572891 ← 收到响应
[心跳] 检查: 距上次消息 5002ms, 超时阈值 8000ms
[心跳] ⚠️ 检测到超时,关闭连接 ← 没收到响应
[关闭] 连接关闭: isTimeoutClose=true
[关闭] 是否重连: true