自用基于 TypeScript 的 WebSocket 客户端封装

代码本体

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);
  },
});
相关推荐
老毛肚8 小时前
jeecg-boot-base-core 02 day
javascript·python
hrw_embedded11 小时前
国外新能源充电平台调试OCPP调试平台SteVe和Monta其实是互补的-websoket连接部分。
websocket·ocpp·新能源充电平台·steve·monta
烬羽13 小时前
后端返回的 JSON 字符串,浏览器怎么"看懂"的?——Ajax 全链路拆解
javascript
半个落月14 小时前
一个新手用 Bun + Axios 调通 DeepSeek API 的实践记录
javascript
不好听61314 小时前
深入理解链表:线性数据结构的另一面
javascript·数据结构
林希_Rachel_傻希希14 小时前
学React治好了我的焦虑症,1小时速通React 前20分钟。
前端·javascript·面试
小林ixn14 小时前
从 Ajax 到异步编程:JSON 序列化、Event Loop 与 XHR 请求完全解析
javascript
JouYY15 小时前
如何实现基于 WebSocket Agent 的断线重连与状态恢复
websocket·llm·agent
丷丩16 小时前
MapLibre GL JS第47课:添加动画图标
javascript·gis·动画·mapbox·maplibre
快乐的哈士奇16 小时前
【Next.js实战①】Gmail API 按柜号检索邮件:OAuth 双 Cookie 与搜索 Fallback
开发语言·javascript·ecmascript