封装代码如下:
TypeScript
type EventHandler<T> = (event: T) => void;
class WebSocketTool {
private ws: WebSocket | null = null;
private url: string;
private isOpen: boolean = false;
private readonly pingTimeout: number = 10000;
private readonly pongTimeout: number = 1000;
private pingTimeoutId: ReturnType<typeof setTimeout> | null = null;
private pongTimeoutId: ReturnType<typeof setTimeout> | null = null;
private isReconnecting: boolean = false;
private reconnectTimeout: number = 1000;
public onopen: EventHandler<Event> | null = null;
public onclose: EventHandler<CloseEvent> | null = null;
public onmessage: EventHandler<MessageEvent> | null = null;
public onerror: EventHandler<Event> | null = null;
constructor(url: string) {
this.url = url;
this.connect();
}
private connect(): void {
this.ws = new WebSocket(this.url);
this.ws.onopen = event => this.handleOpen(event);
this.ws.onclose = event => this.handleClose(event);
this.ws.onerror = event => this.handleError(event);
this.ws.onmessage = event => this.handleMessage(event);
}
private handleOpen(event: Event): void {
if (this.ws?.readyState != 1) {
return;
}
this.isOpen = true;
if (this.onopen) {
this.onopen(event);
}
this.startHeartbeat();
}
private handleMessage(event: MessageEvent): void {
if (this.onmessage) {
this.onmessage(event);
}
this.resetHeartbeat();
this.startHeartbeat();
}
private handleClose(event: CloseEvent): void {
this.isOpen = false;
if (this.onclose) {
this.onclose(event);
}
}
private handleError(event: Event): void {
if (this.onerror) {
this.onerror(event);
}
this.reconnect();
}
private reconnect(): void {
if (this.isReconnecting) return;
this.isReconnecting = true;
setTimeout(() => {
this.connect();
this.isReconnecting = false;
}, this.reconnectTimeout);
}
private startHeartbeat(): void {
this.pingTimeoutId = setTimeout(() => {
if (this.isOpen) {
this.resetHeartbeat();
return;
}
this.pongTimeoutId = setTimeout(() => {
console.log("心跳超时,准备重连");
this.reconnect();
}, this.pongTimeout);
}, this.pingTimeout);
}
private resetHeartbeat(): void {
if (this.pingTimeoutId) {
clearTimeout(this.pingTimeoutId);
}
if (this.pongTimeoutId) {
clearTimeout(this.pongTimeoutId);
}
}
public send(message: string): void {
if (this.ws && this.isOpen) {
this.ws.send(message);
} else {
console.error("WebSocket 连接未打开,无法发送消息");
}
}
public close(): void {
if (this.ws) {
this.ws.close();
}
this.resetHeartbeat();
}
}
export default WebSocketTool;
页面使用时:
TypeScript
// 建立webSocket连接
const ws = new WebSocketTool("/websocket?Authorization=" + token);
ws.onopen = (event: Event) => {
console.log("WebSocket 连接已打开", event);
};
ws.onmessage = (event: MessageEvent) => {
const message = JSON.parse(event.data);
console.log("收到消息:", message);
};
ws.onclose = (event: CloseEvent) => {
console.log("WebSocket 连接已关闭:", event);
};
ws.onerror = (event: Event) => {
console.log("WebSocket 错误:", event);
};
页面销毁时:
TypeScript
onBeforeUnmount(() => {
// 关闭连接
ws.close();
});