websoket-vue3Hooks扩展版
<template>
<div>
<p>连接状态: {{ statusText }}</p>
<p v-if="reconnectCount > 0">已尝试重连: {{ reconnectCount }} 次</p>
<p v-if="isReachLimit" class="error">已达到最大重连次数,停止自动重连</p>
<button v-if="isReachLimit" @click="resetRetry">手动重试</button>
</div>
</template>
<script setup>
import { ref, reactive, computed, onMounted, onBeforeUnmount } from 'vue'
const ReadyState = {
CONNECTING: 0,
OPEN: 1,
CLOSING: 2,
CLOSED: 3
}
const useWebSocket = (url, options = {}) => {
const config = reactive({
reconnectInterval: 1000,
maxReconnectInterval: 30000,
reconnectDecay: 1.5,
autoReconnect: true,
maxRetries: 5, // 默认改为有限次数
onMaxRetries: null, // 新增最大尝试回调
...options
})
// 响应式状态
const wsInstance = ref(null)
const reconnectCount = ref(0)
const manualClose = ref(false)
const status = ref(ReadyState.CLOSED)
const isReachLimit = ref(false)
// 计算属性
const statusText = computed(() => {
const texts = {
[ReadyState.CONNECTING]: '连接中...',
[ReadyState.OPEN]: '已连接',
[ReadyState.CLOSING]: '关闭中',
[ReadyState.CLOSED]: isReachLimit.value ? '已停止重连' : '已断开'
}
return texts[status.value] || '未知状态'
})
// 核心连接逻辑
const connect = () => {
if (isReachLimit.value) return
manualClose.value = false
wsInstance.value = new WebSocket(url)
status.value = ReadyState.CONNECTING
wsInstance.value.onopen = (event) => {
reconnectCount.value = 0
isReachLimit.value = false
status.value = ReadyState.OPEN
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()
}
}
// 其他事件监听保持不变...
}
// 增强的重连调度
const scheduleReconnect = () => {
if (shouldStopReconnect()) {
handleReconnectLimit()
return
}
const delay = calculateDelay()
setTimeout(() => {
reconnectCount.value++
connect()
}, delay)
}
// 判断是否停止重连
const shouldStopReconnect = () => {
return (
!config.autoReconnect ||
manualClose.value ||
reconnectCount.value >= config.maxRetries
)
}
// 处理重连限制
const handleReconnectLimit = () => {
if (reconnectCount.value >= config.maxRetries) {
isReachLimit.value = true
config.onMaxRetries?.(reconnectCount.value)
}
}
// 计算延迟时间(带随机抖动)
const calculateDelay = () => {
const baseDelay = Math.min(
config.reconnectInterval * Math.pow(config.reconnectDecay, reconnectCount.value),
config.maxReconnectInterval
)
return baseDelay + Math.random() * 500 // 添加随机抖动避免惊群效应
}
// 新增重置方法
const resetRetry = () => {
reconnectCount.value = 0
isReachLimit.value = false
connect()
}
// 暴露给组件的API
return {
send: (data) => { /* 保持不变 */ },
close: () => { /* 保持不变 */ },
resetRetry,
status,
statusText,
reconnectCount,
isReachLimit
}
}
// 使用示例
const {
resetRetry,
isReachLimit,
statusText,
reconnectCount
} = useWebSocket('wss://echo.websocket.org', {
onOpen: (event) => {
console.log('连接成功', event)
},
onMaxRetries: (count) => {
console.warn(`已达到最大重连次数 ${count} 次`)
// 可以在这里触发UI通知
},
maxRetries: 3 // 设置自定义重试次数
})
</script>
<style>
.error {
color: #ff4444;
font-weight: bold;
}
</style>