自用基于 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);
  },
});
相关推荐
2501_916013744 小时前
从一次被抄袭经历谈起:iOS App 安全保护实战
websocket·网络协议·tcp/ip·http·网络安全·https·udp
成都渲染101云渲染66665 小时前
blender云渲染指南2025版
前端·javascript·网络·blender·maya
聆听+自律5 小时前
css实现渐变色圆角边框,背景色自定义
前端·javascript·css
行走__Wz5 小时前
计算机学习路线与编程语言选择(信息差)
java·开发语言·javascript·学习·编程语言选择·计算机学习路线
-代号95275 小时前
【JavaScript】二十九、垃圾回收 + 闭包 + 变量提升
开发语言·javascript·ecmascript
halo14166 小时前
vue中scss使用js的变量
javascript·vue3·scss
Mr.闻吉安6 小时前
什么是变量提升?
javascript·es6
huohuopro6 小时前
Vue3快速入门/Vue3基础速通
前端·javascript·vue.js·前端框架
草巾冒小子6 小时前
vue3中解决 return‘ inside ‘finally‘ block报错的问题
前端·javascript·vue.js
MossGrower7 小时前
65.Three.js案例-使用 MeshNormalMaterial 和 MeshDepthMaterial 创建 3D 图形
javascript·threejs·spheregeometry·torusknotgeome