代码本体
typescript
export interface IWSOptions {
url?: string;
sendContent?: string | object;
token?: string;
reconnectInterval?: number;
heartbeatInterval?: number;
heartbeatContent?: string | object;
onOpen?: () => void;
onMessage?: (data: any) => void;
onClose?: (event: Event) => void;
onError?: (error: Event) => void;
}
export class WebSocketClient {
private ws: WebSocket | null = null;
private reconnectInterval: number = 2000;
private heartbeatInterval: number = 1000;
private heartbeatTimer: ReturnType<typeof setInterval> | null = null;
private reconnectTimer: ReturnType<typeof setTimeout> | null = null;
constructor(private options: IWSOptions) {
this.reconnectInterval =
options.reconnectInterval ?? this.reconnectInterval;
this.heartbeatInterval =
options.heartbeatInterval ?? this.heartbeatInterval;
this.init();
}
private init() {
this.ws = new WebSocket(
this.options.url ?? import.meta.env.VITE_HW_ADDRESS
);
this.ws.onopen = this.handleOpen;
this.ws.onmessage = this.handleMessage;
this.ws.onerror = this.handleError;
this.ws.onclose = this.handleClose;
}
private handleOpen = (_event: Event) => {
this.clearReconnect();
this.sendInitMessage();
this.startHeartbeat();
this.options.onOpen?.();
};
private handleMessage = (e: MessageEvent) => {
this.options.onMessage?.(e.data);
};
private handleError = (e: ErrorEvent) => {
this.options.onError?.(e);
};
private handleClose = (e: CloseEvent) => {
this.clearHeartbeat();
this.startReconnect();
this.options.onClose?.(e);
};
private sendInitMessage() {
if (this.options.sendContent) {
this.send(this.options.sendContent);
}
}
private sendHeartbeat() {
if (this.options.heartbeatContent) {
this.send(this.options.heartbeatContent);
}
}
private send(content: string | object) {
const message =
typeof content === "string" ? content : JSON.stringify(content);
this.ws?.send(message);
}
private startHeartbeat() {
if (this.heartbeatInterval > 0) {
this.heartbeatTimer = setInterval(
() => this.sendHeartbeat(),
this.heartbeatInterval
);
}
}
private clearHeartbeat() {
if (this.heartbeatTimer) {
clearInterval(this.heartbeatTimer);
this.heartbeatTimer = null;
}
}
private startReconnect() {
if (this.reconnectInterval > 0) {
this.reconnectTimer = setTimeout(() => {
this.init();
}, this.reconnectInterval);
}
}
private clearReconnect() {
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer);
this.reconnectTimer = null;
}
}
public close() {
this.clearHeartbeat();
this.clearReconnect();
this.ws?.close();
this.ws = null;
}
}
使用例
typescript
import { WebSocketClient } from "./websocket";
new WebSocketClient({
sendContent: {
message: "hello from tshihcin!",
},
reconnectInterval: 3000,
heartbeatInterval: 1500,
onMessage: (data: any) => {
console.log(data);
},
onError: (e: Event) => {
console.log(e);
},
});