feat(websocket): 实现 WebSocket通信功能

- 新增 useWebSocket 组合式函数,用于在组件中使用 WebSocket
- 添加 WebSocket 插件,提供全局 WebSocket 实例和相关方法
- 实现了连接、重连、发送消息、关闭连接等功能
- 通过自定义事件实现消息广播,供组件监听
This commit is contained in:
xingyy 2025-01-23 16:37:11 +08:00
parent e2b5e6bcbf
commit 65f8d2d1e9
3 changed files with 9246 additions and 0 deletions

View File

@ -0,0 +1,21 @@
export function useWebSocket() {
const { $ws } = useNuxtApp()
const messages = ref<any[]>([])
// 监听消息
const onMessage = (callback: (data: any) => void) => {
const handler = (event: CustomEvent) => callback(event.detail)
window.addEventListener('ws-message', handler as EventListener)
// 返回清理函数
return () => {
window.removeEventListener('ws-message', handler as EventListener)
}
}
return {
ws: $ws,
messages,
onMessage
}
}

86
app/plugins/websocket.ts Normal file
View File

@ -0,0 +1,86 @@
export default defineNuxtPlugin(() => {
const config = useRuntimeConfig()
const ws = reactive({
instance: null as WebSocket | null,
isConnected: false,
// 修改 connect 方法接收路径和数据对象
connect(path: string, data?: Record<string, any>) {
if (this.instance?.readyState === WebSocket.OPEN) {
this.instance.close()
}
// 构建查询字符串
const queryString = data
? '?' + Object.entries(data)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join('&')
: ''
// 构建完整的 WebSocket URL
const wsUrl = `${config.public.NUXT_PUBLIC_SOCKET_URL}${path}${queryString}`
this.instance = new WebSocket(wsUrl)
this.instance.onopen = () => {
this.isConnected = true
console.log('WebSocket 已连接')
}
this.instance.onclose = () => {
this.isConnected = false
console.log('WebSocket 已断开')
/* this.reconnect(path, data)*/
}
this.instance.onerror = (error) => {
console.error('WebSocket 错误:', error)
}
this.instance.onmessage = (event) => {
try {
const data = JSON.parse(event.data)
this.handleMessage(data)
} catch (error) {
console.error('消息解析错误:', error)
}
}
},
// 更新重连方法以支持数据对象
reconnect(path: string, data?: Record<string, any>) {
setTimeout(() => {
console.log('尝试重新连接...')
this.connect(path, data)
}, 3000)
},
// 发送消息
send(data: any) {
if (this.instance?.readyState === WebSocket.OPEN) {
this.instance.send(JSON.stringify(data))
} else {
console.warn('WebSocket 未连接,无法发送消息')
}
},
// 关闭连接
disconnect() {
if (this.instance) {
this.instance.close()
this.instance = null
}
},
// 消息处理
handleMessage(data: any) {
// 触发自定义事件,让组件可以监听
window.dispatchEvent(new CustomEvent('ws-message', { detail: data }))
}
})
return {
provide: {
ws
}
}
})

9139
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff