docs(websocket): 添加useWebSocket参考文档

This commit is contained in:
MoeSnowyFox
2025-10-01 18:06:24 +08:00
parent 1eae8c80e5
commit 3d204980a2
2 changed files with 763 additions and 0 deletions

View File

@@ -0,0 +1,427 @@
# useWebSocket API 参考文档
## 概述
`useWebSocket()` 组合式函数提供了完整的 WebSocket 通信接口,包含消息订阅、连接管理、状态监控等核心功能。
## 导出函数详解
### 1. subscribe() - 订阅消息
```typescript
const subscribe = (
filter: SubscriptionFilter,
handler: (message: WebSocketBaseMessage) => void
): string
```
#### 参数说明
**filter: SubscriptionFilter**
```typescript
interface SubscriptionFilter {
type?: string // 消息类型过滤器(可选)
id?: string // 消息ID过滤器可选
needCache?: boolean // 是否启用缓存回放(可选)
}
```
**handler: Function**
- 消息处理回调函数
- 参数: `message: WebSocketBaseMessage`
- 无返回值
#### 返回值
- `string`: 唯一的订阅ID用于后续取消订阅
#### 使用示例
```typescript
// 订阅所有消息
const allMsgSub = subscribe({}, (msg) => {
console.log('收到消息:', msg)
})
// 订阅特定类型消息
const taskSub = subscribe(
{ type: 'TaskUpdate', needCache: true },
(msg) => {
console.log('任务更新:', msg.data)
}
)
// 订阅特定ID消息
const specificSub = subscribe(
{ id: 'TaskManager' },
(msg) => {
console.log('任务管理器消息:', msg)
}
)
// 精确订阅同时匹配type和id
const preciseSub = subscribe(
{ type: 'Progress', id: 'task_001', needCache: true },
(msg) => {
console.log('特定任务进度:', msg.data)
}
)
```
#### 特殊功能
- **自动回放**: 如果 `needCache: true`,会立即回放匹配的历史消息
- **过滤优先级**: type + id > type > id > 全部
- **引用计数**: 多个订阅共享缓存,自动管理内存
---
### 2. unsubscribe() - 取消订阅
```typescript
const unsubscribe = (subscriptionId: string): void
```
#### 参数说明
**subscriptionId: string**
-`subscribe()` 返回的订阅ID
- 必须是有效的订阅ID
#### 使用示例
```typescript
const subId = subscribe({ type: 'TaskUpdate' }, handleTaskUpdate)
// 取消订阅
unsubscribe(subId)
// Vue 组件中的最佳实践
import { onUnmounted } from 'vue'
const setupSubscription = () => {
const subId = subscribe({ type: 'TaskUpdate' }, handleTaskUpdate)
onUnmounted(() => {
unsubscribe(subId)
})
}
```
#### 自动清理
- 自动减少缓存引用计数
- 引用计数为0时清理相关缓存
- 不会影响其他订阅者
---
### 3. sendRaw() - 发送消息
```typescript
const sendRaw = (type: string, data?: any, id?: string): void
```
#### 参数说明
**type: string** (必需)
- 消息类型标识
- 后端用于路由消息
**data: any** (可选)
- 消息负载数据
- 可以是任何可序列化的对象
**id: string** (可选)
- 消息标识符
- 用于消息跟踪和响应匹配
#### 使用示例
```typescript
// 发送简单消息
sendRaw('Hello')
// 发送带数据的消息
sendRaw('TaskStart', {
taskId: '12345',
config: { timeout: 30000 }
})
// 发送带ID的消息便于追踪响应
sendRaw('GetTaskStatus', { taskId: '12345' }, 'query_001')
// 发送控制信号
sendRaw('Signal', {
command: 'pause',
reason: '用户手动暂停'
}, 'TaskManager')
```
#### 发送条件
- 仅在 WebSocket 连接为 `OPEN` 状态时发送
- 连接异常时静默失败(不抛出异常)
- 自动JSON序列化
---
### 4. getConnectionInfo() - 获取连接信息
```typescript
const getConnectionInfo = (): ConnectionInfo
```
#### 返回值类型
```typescript
interface ConnectionInfo {
connectionId: string // 连接唯一标识
status: WebSocketStatus // 当前连接状态
subscriberCount: number // 当前订阅者数量
moduleLoadCount: number // 模块加载计数
wsReadyState: number | null // WebSocket原生状态
isConnecting: boolean // 是否正在连接
hasHeartbeat: boolean // 是否启用心跳
hasEverConnected: boolean // 是否曾经连接成功
reconnectAttempts: number // 重连尝试次数
isPersistentMode: boolean // 是否持久化模式
}
```
#### 使用示例
```typescript
const info = getConnectionInfo()
console.log('连接ID:', info.connectionId)
console.log('连接状态:', info.status)
console.log('订阅者数量:', info.subscriberCount)
// 检查连接是否健康
const isHealthy = info.status === '已连接' &&
info.hasHeartbeat &&
info.wsReadyState === WebSocket.OPEN
// 监控重连情况
if (info.reconnectAttempts > 0) {
console.log(`已重连 ${info.reconnectAttempts} 次`)
}
```
#### 调试用途
- 诊断连接问题
- 监控连接质量
- 统计使用情况
---
### 5. status - 连接状态
```typescript
const status: Ref<WebSocketStatus>
```
#### 状态类型
```typescript
type WebSocketStatus = '连接中' | '已连接' | '已断开' | '连接错误'
```
#### 状态说明
| 状态 | 描述 | 触发条件 |
|------|------|----------|
| `'连接中'` | 正在建立连接 | WebSocket.CONNECTING |
| `'已连接'` | 连接成功 | WebSocket.OPEN |
| `'已断开'` | 连接断开 | WebSocket.CLOSED |
| `'连接错误'` | 连接异常 | WebSocket.onerror |
#### 使用示例
```typescript
import { watch } from 'vue'
const { status } = useWebSocket()
// 监听状态变化
watch(status, (newStatus) => {
console.log('连接状态变化:', newStatus)
switch (newStatus) {
case '已连接':
console.log('✅ WebSocket 连接成功')
break
case '已断开':
console.log('❌ WebSocket 连接断开')
break
case '连接错误':
console.log('⚠️ WebSocket 连接错误')
break
case '连接中':
console.log('🔄 WebSocket 连接中...')
break
}
})
// 在模板中显示状态
// <div>连接状态: {{ status }}</div>
```
#### 响应式特性
- Vue 响应式 Ref 对象
- 自动更新 UI
- 可用于计算属性和监听器
---
### 6. backendStatus - 后端状态
```typescript
const backendStatus: Ref<BackendStatus>
```
#### 状态类型
```typescript
type BackendStatus = 'unknown' | 'starting' | 'running' | 'stopped' | 'error'
```
#### 状态说明
| 状态 | 描述 | 含义 |
|------|------|------|
| `'unknown'` | 未知状态 | 初始状态,尚未检测 |
| `'starting'` | 启动中 | 后端服务正在启动 |
| `'running'` | 运行中 | 后端服务正常运行 |
| `'stopped'` | 已停止 | 后端服务已停止 |
| `'error'` | 错误状态 | 后端服务异常 |
#### 使用示例
```typescript
const { backendStatus, restartBackend } = useWebSocket()
// 监听后端状态
watch(backendStatus, (newStatus) => {
console.log('后端状态:', newStatus)
switch (newStatus) {
case 'running':
console.log('✅ 后端服务运行正常')
break
case 'stopped':
console.log('⏹️ 后端服务已停止')
break
case 'error':
console.log('❌ 后端服务异常')
// 可以提示用户或自动重启
break
case 'starting':
console.log('🚀 后端服务启动中...')
break
}
})
// 根据状态显示不同UI
const statusColor = computed(() => {
switch (backendStatus.value) {
case 'running': return 'green'
case 'error': return 'red'
case 'starting': return 'orange'
default: return 'gray'
}
})
```
#### 自动管理
- 每3秒自动检测一次
- 异常时自动尝试重启最多3次
- 集成 Electron 进程管理
---
## 完整使用示例
```typescript
import { onMounted, onUnmounted, watch } from 'vue'
import { useWebSocket } from '@/composables/useWebSocket'
export default {
setup() {
const {
subscribe,
unsubscribe,
sendRaw,
getConnectionInfo,
status,
backendStatus
} = useWebSocket()
let taskSubscription: string
let systemSubscription: string
onMounted(() => {
// 订阅任务消息
taskSubscription = subscribe(
{ type: 'TaskUpdate', needCache: true },
(message) => {
console.log('任务更新:', message.data)
}
)
// 订阅系统消息
systemSubscription = subscribe(
{ id: 'System' },
(message) => {
console.log('系统消息:', message)
}
)
// 发送初始化消息
sendRaw('ClientReady', {
timestamp: Date.now()
}, 'System')
})
onUnmounted(() => {
// 清理订阅
if (taskSubscription) unsubscribe(taskSubscription)
if (systemSubscription) unsubscribe(systemSubscription)
})
// 监听连接状态
watch([status, backendStatus], ([wsStatus, beStatus]) => {
console.log(`WS: ${wsStatus}, Backend: ${beStatus}`)
})
// 获取连接信息
const connectionInfo = getConnectionInfo()
return {
status,
backendStatus,
connectionInfo,
sendMessage: (type: string, data: any) => sendRaw(type, data)
}
}
}
```
## 最佳实践
### 1. 订阅管理
- 总是在组件卸载时取消订阅
- 使用 `needCache: true` 确保不丢失消息
- 避免重复订阅相同的消息类型
### 2. 错误处理
- 监听连接状态变化
- 根据后端状态调整UI显示
- 实现重连提示和手动重启
### 3. 性能优化
- 精确的过滤条件减少不必要的处理
- 合理使用缓存避免消息丢失
- 及时取消不需要的订阅
### 4. 调试技巧
- 使用 `getConnectionInfo()` 诊断问题
- 开发环境下查看控制台日志
- 监控订阅者数量避免内存泄漏

View File

@@ -0,0 +1,336 @@
## 核心架构设计
### 1. 全局持久化存储
```typescript
const WS_STORAGE_KEY = Symbol.for('GLOBAL_WEBSOCKET_PERSISTENT')
```
- 使用 `Symbol.for()` 确保全局唯一性
- 存储在 `window` 对象上,实现跨组件共享
- 避免多次实例化,确保连接唯一性
### 2. 状态管理结构
```typescript
interface GlobalWSStorage {
wsRef: WebSocket | null // WebSocket 实例
status: Ref<WebSocketStatus> // 连接状态
subscriptions: Ref<Map<string, WebSocketSubscription>> // 订阅管理
cacheMarkers: Ref<Map<string, CacheMarker>> // 缓存标记
cachedMessages: Ref<Array<CachedMessage>> // 消息缓存
// ... 其他状态
}
```
## 核心功能模块
### 1. 配置管理
```typescript
const BASE_WS_URL = 'ws://localhost:36163/api/core/ws'
const HEARTBEAT_INTERVAL = 15000 // 心跳间隔
const HEARTBEAT_TIMEOUT = 5000 // 心跳超时
const BACKEND_CHECK_INTERVAL = 3000 // 后端检查间隔
const MAX_RESTART_ATTEMPTS = 3 // 最大重启尝试次数
const RESTART_DELAY = 2000 // 重启延迟
const MAX_QUEUE_SIZE = 50 // 最大队列大小
const MESSAGE_TTL = 60000 // 消息过期时间
```
**要点**:
- 所有时间配置使用毫秒为单位
- 可根据网络环境调整超时时间
- 队列大小限制防止内存泄漏
### 2. 消息订阅系统
#### 订阅过滤器
```typescript
interface SubscriptionFilter {
type?: string // 消息类型过滤
id?: string // 消息ID过滤
needCache?: boolean // 是否需要缓存
}
```
#### 订阅机制
```typescript
export const subscribe = (
filter: SubscriptionFilter,
handler: (message: WebSocketBaseMessage) => void
): string => {
// 1. 生成唯一订阅ID
// 2. 创建订阅记录
// 3. 添加缓存标记
// 4. 回放匹配的缓存消息
}
```
**要点**:
- 支持按 `type``id` 的组合过滤
- 自动回放缓存消息,确保不丢失历史数据
- 返回订阅ID用于后续取消订阅
### 3. 智能缓存系统
#### 缓存标记机制
```typescript
interface CacheMarker {
type?: string
id?: string
refCount: number // 引用计数
}
```
#### 缓存策略
- **引用计数**: 订阅时 +1取消订阅时 -1
- **自动清理**: 引用计数为 0 时删除标记
- **TTL机制**: 消息超过 60 秒自动过期
- **大小限制**: 每个队列最多保留 50 条消息
### 4. 心跳检测机制
```typescript
const startGlobalHeartbeat = (ws: WebSocket) => {
global.heartbeatTimer = window.setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
const pingTime = Date.now()
global.lastPingTime = pingTime
ws.send(JSON.stringify({
type: 'Signal',
data: { Ping: pingTime, connectionId: global.connectionId }
}))
}
}, HEARTBEAT_INTERVAL)
}
```
### 5. 后端服务监控
#### 状态检测
```typescript
type BackendStatus = 'unknown' | 'starting' | 'running' | 'stopped' | 'error'
```
#### 自动重启逻辑
```typescript
const restartBackend = async (): Promise<boolean> => {
// 1. 防重入检查
// 2. 递增重启计数
// 3. 调用 Electron API 启动后端
// 4. 更新状态
}
```
### 6. 连接控制机制
#### 连接权限控制
```typescript
const allowedConnectionReasons = ['后端启动后连接', '后端重启后重连']
const checkConnectionPermission = () => getGlobalStorage().allowNewConnection
```
#### 连接锁机制
```typescript
let isGlobalConnectingLock = false
const acquireConnectionLock = () => {
if (isGlobalConnectingLock) return false
isGlobalConnectingLock = true
return true
}
```
**AI 开发要点**:
- 防止并发连接导致的竞态条件
- 只允许特定原因的连接请求
- 确保全局唯一连接
## 消息流处理
### 1. 消息匹配算法
```typescript
const messageMatchesFilter = (message: WebSocketBaseMessage, filter: SubscriptionFilter): boolean => {
// 如果都不指定,匹配所有消息
if (!filter.type && !filter.id) return true
// 如果只指定type
if (filter.type && !filter.id) return message.type === filter.type
// 如果只指定id
if (!filter.type && filter.id) return message.id === filter.id
// 如果同时指定type和id必须都匹配
return message.type === filter.type && message.id === filter.id
}
```
### 2. 消息分发流程
```
WebSocket 接收消息
JSON 解析
遍历所有订阅者
匹配过滤条件
调用处理器函数
检查是否需要缓存
添加到缓存队列
```
## 外部接口设计
### 1. 主要导出函数
```typescript
export function useWebSocket() {
return {
subscribe, // 订阅消息
unsubscribe, // 取消订阅
sendRaw, // 发送消息
getConnectionInfo, // 获取连接信息
status, // 连接状态
backendStatus, // 后端状态
restartBackend, // 重启后端
getBackendStatus, // 获取后端状态
}
}
```
### 2. 特殊接口
```typescript
export const connectAfterBackendStart = async (): Promise<boolean>
```
- 后端启动后的连接入口
- 启动后端监控
- 设置连接权限
## 错误处理策略
### 1. 连接错误处理
- WebSocket 连接失败时设置状态为 '连接错误'
- 通过后端监控检测服务状态
- 自动重启后端服务
### 2. 消息处理错误
- 订阅处理器异常时记录警告但不中断其他订阅者
- JSON 解析失败时静默忽略
- 发送消息失败时静默处理
### 3. 后端故障处理
```typescript
const handleBackendFailure = async () => {
if (global.backendRestartAttempts >= MAX_RESTART_ATTEMPTS) {
// 显示错误对话框,提示重启应用
Modal.error({
title: '后端服务异常',
content: '后端服务多次重启失败,请重启整个应用程序。'
})
return
}
// 自动重启逻辑
}
```
## 调试和监控
### 1. 调试模式
```typescript
const DEBUG = process.env.NODE_ENV === 'development'
const log = (...args: any[]) => {
if (DEBUG) console.log('[WebSocket]', ...args)
}
```
### 2. 连接信息监控
```typescript
const getConnectionInfo = () => ({
connectionId: global.connectionId,
status: global.status.value,
subscriberCount: global.subscriptions.value.size,
moduleLoadCount: global.moduleLoadCount,
wsReadyState: global.wsRef ? global.wsRef.readyState : null,
isConnecting: global.isConnecting,
hasHeartbeat: !!global.heartbeatTimer,
hasEverConnected: global.hasEverConnected,
reconnectAttempts: global.reconnectAttempts,
isPersistentMode: true,
})
```
## AI 开发建议
### 1. 使用模式
```typescript
// 在 Vue 组件中使用
const { subscribe, unsubscribe, sendRaw, status } = useWebSocket()
// 订阅特定类型消息
const subId = subscribe(
{ type: 'TaskUpdate', needCache: true },
(message) => {
console.log('收到任务更新:', message.data)
}
)
// 组件卸载时取消订阅
onUnmounted(() => {
unsubscribe(subId)
})
```
### 2. 扩展建议
- 添加消息重试机制
- 实现消息优先级队列
- 支持消息压缩
- 添加连接质量监控
### 3. 性能优化点
- 使用 `Object.freeze()` 冻结配置对象
- 考虑使用 Web Worker 处理大量消息
- 实现消息批处理机制
- 添加消息去重功能
### 4. 安全考虑
- 验证消息来源
- 实现消息签名机制
- 添加连接认证
- 防止消息注入攻击
## 依赖关系
### 1. 外部依赖
- `vue`: 响应式系统和组合式API
- `ant-design-vue`: UI组件库Modal
- `schedulerHandlers`: 默认消息处理器
### 2. 运行时依赖
- `window.electronAPI`: Electron主进程通信
- WebSocket API: 浏览器原生支持
## 总结
这个 WebSocket 组合式函数是一个功能完整、设计精良的实时通信解决方案。它不仅解决了基本的 WebSocket 连接问题,还提供了高级功能如智能缓存、自动重连、后端监控等。
**核心优势**:
1. 全局持久化连接,避免重复建立
2. 智能订阅系统,支持精确过滤
3. 自动缓存回放,确保数据完整性
4. 完善的错误处理和自动恢复
5. 详细的调试和监控信息
**适用场景**:
- 实时数据展示
- 任务状态监控
- 系统通知推送
- 双向通信应用