websocket前端封装简易版

28 阅读1分钟
/**
 * WebSocket 消息处理器
 */
export type MessageHandler<T = any> = (data: T, timestamp: number) => void;
/**
 * 简单的 WebSocket 连接类
 * 适用于基本的 WebSocket 连接,不需要 STOMP 协议
 */
export class SimpleWebSocket {
  private ws: WebSocket | null = null;
  private reconnectAttempts = 0;
  private isManualClose = false;
  public isConnected = false;
  public lastMessageTime = 0;

  private onMessage?: MessageHandler;
  private onOpen?: () => void;
  private onClose?: () => void;
  private onError?: (error: Event) => void;
  private reconnectInterval: number;
  private maxReconnectAttempts: number;
  private url: string;

  constructor(
    url: string,
    options: {
      onMessage?: MessageHandler;
      onOpen?: () => void;
      onClose?: () => void;
      onError?: (error: Event) => void;
      reconnectInterval?: number;
      maxReconnectAttempts?: number;
    } = {}
  ) {
    this.url = url;
    this.onMessage = options.onMessage;
    this.onOpen = options.onOpen;
    this.onClose = options.onClose;
    this.onError = options.onError;
    this.reconnectInterval = options.reconnectInterval || 5000;
    this.maxReconnectAttempts = options.maxReconnectAttempts || 5;
    // 自动连接
    this.connect();
  }

  private connect() {
    try {
      this.ws = new WebSocket(this.url);
      this.ws.onopen = () => {
        this.isConnected = true;
        this.reconnectAttempts = 0;
        this.onOpen?.();
      };

      this.ws.onmessage = (event) => {
        try {
          const data = JSON.parse(event.data);
          const timestamp = Date.now();
          this.lastMessageTime = timestamp;
          this.onMessage?.(data, timestamp);
        } catch (error) {
          console.error("[ChatChannel] 解析消息失败:", error);
          this.onMessage?.(event.data, Date.now());
        }
      };

      this.ws.onclose = () => {
        this.isConnected = false;
        this.onClose?.();

        if (!this.isManualClose && this.reconnectAttempts < this.maxReconnectAttempts) {
          setTimeout(() => {
            this.reconnectAttempts++;
            console.log(`[ChatChannel] 尝试重连 (${this.reconnectAttempts})`);
            this.connect();
          }, this.reconnectInterval);
        }
      };

      this.ws.onerror = (error) => {
        console.error("[ChatChannel] 连接错误:", error);
        this.onError?.(error);
      };
    } catch (error) {
      console.error("[ChatChannel] 连接失败:", error);
    }
  }

  public disconnect() {
    this.isManualClose = true;
    if (this.ws) {
      this.ws.close();
      this.ws = null;
    }
  }

  public send(data: any) {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(typeof data === "string" ? data : JSON.stringify(data));
    } else {
      console.warn("[ChatChannel]  未连接");
    }
  }

  public reconnect() {
    this.disconnect();
    this.isManualClose = false;
    this.reconnectAttempts = 0;
    this.connect();
  }
}