websoket-Vue3Hooks封装
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue'
// WebSocket状态枚举
const ReadyState = {
CONNECTING: 0,
OPEN: 1,
CLOSING: 2,
CLOSED: 3
}
// ws://61.163.60.12:19100/im/chat/736fc042-41ab-4f99-8edc-f18a2ebb52f6
const useWebSocket = (url: any, options = {}) => {
// 配置合并
const config: any = reactive({
reconnectInterval: 1000,
maxReconnectInterval: 30000, // 最大重连间隔时间
reconnectDecay: 1.5, // 重连指数衰减 每次间隔翻倍
autoReconnect: true,
maxRetries: Infinity,
...options
})
console.log(config);
// 响应式状态
const wsInstance: any = ref(null)
const reconnectCount = ref(0)
const manualClose = ref(false)
const status = ref(ReadyState.CLOSED)
const statusText = ref('未连接')
// 状态映射文本
const statusMap = {
[ReadyState.CONNECTING]: '连接中...',
[ReadyState.OPEN]: '已连接',
[ReadyState.CLOSING]: '关闭中',
[ReadyState.CLOSED]: '已断开'
}
// 初始化连接
const connect = () => {
manualClose.value = false
wsInstance.value = new WebSocket(url)
console.log('wsInstance', wsInstance.value);
status.value = ReadyState.CONNECTING
// 更新状态文本
const updateStatusText = () => {
statusText.value = statusMap[status.value] || '未知状态'
}
updateStatusText()
// 事件监听
wsInstance.value.onopen = (event: any) => {
reconnectCount.value = 0
status.value = ReadyState.OPEN
updateStatusText()
config.onOpen?.(event)
}
wsInstance.value.onmessage = (event: any) => {
config.onMessage?.(event.data)
}
wsInstance.value.onclose = (event: any) => {
status.value = ReadyState.CLOSED
updateStatusText()
config.onClose?.(event)
if (!manualClose.value && config.autoReconnect) {
scheduleReconnect()
}
}
wsInstance.value.onerror = (error: any) => {
status.value = ReadyState.CLOSED
updateStatusText()
config.onError?.(error)
wsInstance.value?.close()
}
}
// 计划重连
const scheduleReconnect = () => {
if (reconnectCount.value >= config.maxRetries) return
const delay = Math.min(
config.reconnectInterval * Math.pow(config.reconnectDecay, reconnectCount.value),
config.maxReconnectInterval
)
setTimeout(() => {
reconnectCount.value++
connect()
}, delay)
}
// 发送消息
const send = (data: any) => {
if (wsInstance.value?.readyState === WebSocket.OPEN) {
wsInstance.value.send(data)
} else {
console.error('消息发送失败: WebSocket未连接')
}
}
// 手动关闭
const close = () => {
manualClose.value = true
wsInstance.value?.close()
}
// 组件挂载时自动连接
onMounted(() => {
// 自动绑定创建组件生命周期
connect()
})
/* // 组件卸载时关闭连接
onBeforeUnmount(() => {
console.log('onBeforeUnmountclose',wsInstance.value);
close()
}) */
return {
send,
close,
status,
statusText,
reconnectCount,
connect
}
}
export default useWebSocket;
// 在组件中使用
/*
let heartbeatTimer:any;
const {
send,
close,
statusText,
reconnectCount
} = useWebSocket('wss://echo.websocket.org', {
maxRetries: 5, // 最多尝试5次重连 (扩展)
onOpen: (event) => {
console.log('连接成功', event)
heartbeatTimer = setInterval(() => { (扩展)
send('ping') // 发送心跳包
}, 30000)
send('Hello from Vue3!')
},
onMessage: (data) => {
console.log('收到消息:', data)
},
onClose: (event) => {
console.log('连接关闭', event)
clearInterval(heartbeatTimer) (扩展)
if (reconnectCount.value >= 5) {'服务器连接失败,请刷新页面重试'} (扩展)
},
onError: (error) => {
console.error('连接错误:', error)
},
reconnectInterval: 1000,
maxReconnectInterval: 10000
}) */