2025-07-05 16:16:50 +08:00

137 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

export class WsClient {
private socket: WebSocket | null = null
private url: string = 'ws://echo.websocket.org' // 测试服务器
private reconnectTimerId: number = 0
private maxReconnectCount: number = 5
private reconnectCount: number = 0
private isConnected: boolean = false
private static instance: WsClient = null
// 单例
public static Instance(): WsClient {
if (!this.instance) this.instance = new WsClient()
return this.instance
}
// 是否连接
public get IsConnected(): boolean {
return this.isConnected
}
// 关闭WebSocket连接
Close() {
if (this.reconnectTimerId > 0) {
clearTimeout(this.reconnectTimerId)
this.reconnectTimerId = 0
}
if (this.socket) {
// 清空所有事件处理函数
this.socket.onopen = null
this.socket.onmessage = null
this.socket.onclose = null
this.socket.onerror = null
this.socket.close()
this.socket = null
}
this.isConnected = false
}
private async connectAsync(url?: string): Promise<WebSocket> {
if (this.socket && this.socket.readyState !== WebSocket.CLOSED) {
// 如果已有连接且未关闭
this.Close()
}
return new Promise((resolve, reject) => {
const ws = new WebSocket(url)
ws.onopen = () => resolve(ws)
ws.onerror = (err) => reject(err)
ws.onclose = () => reject(new Error('连接已关闭'))
})
}
// // 使用示例
// async function sendMessage() {
// try {
// const ws = await connectWebSocket();
// console.log('连接已建立');
// ws.send('同步发送消息');
// } catch (err) {
// console.error('连接失败:', err);
// }
// }
// 连接websocket服务器
async ConnectAsync(url?: string) {
if (url) this.url = url
url = this.url
try {
console.log(`正在连接websocket服务器:${url}`)
this.socket = await this.connectAsync(url)
this.socket.onopen = this.onOpen.bind(this)
this.socket.onmessage = this.onMessage.bind(this)
this.socket.onclose = this.onClose.bind(this)
this.socket.onerror = this.onError.bind(this)
this.reconnectCount = 0
this.isConnected = true
} catch (error) {
console.error('创建websocket失败:', error)
await this.ScheduleReconnect()
}
}
// 发送消息到服务器
Send(message: Uint8Array) {
if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
// 如果连接不存在或未打开
console.error('websocket未连接,无法发送消息')
return false
}
// var msg: string = ''
// if (typeof message == 'string') {
// msg = message
// } else {
// msg = JSON.stringify(message)
// }
this.socket.send(message)
return true
}
// 连接成功回调
private onOpen() {
console.log('websocket连接已建立')
this.reconnectCount = 0
}
// 收到消息回调
private onMessage(event: MessageEvent) {
console.log('收到消息:', event.data)
window.dispatchEvent(new CustomEvent('ws-message', { detail: event.data }))
}
// 连接关闭回调
private onClose(event: CloseEvent) {
console.log('websocket连接已关闭,代码:', event.code, '原因:', event.reason)
this.socket = null
// this.ScheduleReconnect()
}
// 连接错误回调
private onError(error: Event) {
console.error('websocket发生错误:', error)
// 不需要在这里重连onClose里会重连
}
// 重连
private async ScheduleReconnect() {
if (this.reconnectCount >= this.maxReconnectCount) {
console.error(`达到最大重连次数:${this.maxReconnectCount},停止重连`)
return
}
this.reconnectCount++
console.log(`尝试重连(${this.reconnectCount}/${this.maxReconnectCount})...`)
await this.connectAsync()
}
}