Files
front-pc/utils/WebSocketWithHeartbeatAndReconnect.ts

127 lines
3.8 KiB
TypeScript

export default class WebSocketWithHeartbeatAndReconnect {
private url: string
private socket: WebSocket | null
private heartbeatInterval: number
private pingMessage: string
private pongMessage: string
private reconnectInterval: number
private maxReconnectAttempts: number
private reconnectAttempts: number
private heartbeatTimer: any
private reconnectTimer: any
constructor(url: string, options = {} as any) {
this.url = url
this.socket = null
this.heartbeatInterval = options.heartbeatInterval || 30000 // 默认每 30 秒发送一次心跳
this.pingMessage = options.pingMessage || 'ping' // 默认 ping 消息
this.pongMessage = options.pongMessage || 'pong' // 默认 pong 消息
this.reconnectInterval = options.reconnectInterval || 5000 // 默认每 5 秒尝试重连
this.maxReconnectAttempts = options.maxReconnectAttempts || 5 // 最大重连次数
this.reconnectAttempts = 0 // 当前已尝试的重连次数
this.heartbeatTimer = null // 存储心跳定时器
this.reconnectTimer = null // 存储重连定时器
}
// 初始化 WebSocket 连接
connect() {
if (this.socket) {
this.socket.close() // 关闭现有连接
}
this.socket = new WebSocket(this.url)
// 连接成功时启动心跳
this.socket.onopen = () => {
console.log('WebSocket connected')
this.reconnectAttempts = 0 // 重置重连次数
this.startHeartbeat() // 启动心跳机制
}
// 接收到消息时
this.socket.onmessage = (event) => {
console.log('Received message:', event.data)
// 如果接收到 pong 消息,说明服务器回应了心跳
if (event.data === this.pongMessage) {
console.log('Pong received')
this.resetHeartbeat() // 重置心跳定时器
} else {
this.getMsg(event.data)
}
}
// 连接关闭时
this.socket.onclose = (event) => {
console.log('WebSocket closed:', event)
this.stopHeartbeat() // 停止心跳机制
this.handleReconnect() // 尝试重连
}
// 错误处理
this.socket.onerror = (error) => {
console.error('WebSocket error:', error)
this.socket?.close() // 在发生错误时关闭连接
}
}
// 启动心跳机制,定时发送 ping 消息
startHeartbeat() {
this.heartbeatTimer = setInterval(() => {
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
console.log('Sending ping...')
this.socket.send(this.pingMessage) // 发送 ping 消息
}
}, this.heartbeatInterval)
}
// 重置心跳机制
resetHeartbeat() {
clearInterval(this.heartbeatTimer) // 清除之前的心跳定时器
this.startHeartbeat() // 重新启动心跳定时器
}
// 停止心跳机制
stopHeartbeat() {
clearInterval(this.heartbeatTimer) // 清除心跳定时器
clearTimeout(this.reconnectTimer) // 清除重连定时器
}
// 处理重连机制
handleReconnect() {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++
console.log(`Attempting to reconnect... (${this.reconnectAttempts}/${this.maxReconnectAttempts})`)
// 重连时延
this.reconnectTimer = setTimeout(() => {
this.connect() // 尝试重新连接
}, this.reconnectInterval)
} else {
console.log('Max reconnect attempts reached. Giving up.')
}
}
// 发送数据
send(message: string) {
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
this.socket.send(message)
console.log('Message sent:', message)
} else {
console.log('WebSocket is not open. Cannot send message.')
}
}
// 关闭连接
close() {
if (this.socket) {
this.socket.close()
console.log('WebSocket closed manually.')
}
}
// 接受到的数据
getMsg(val: string) {
console.log(val)
}
}