自用基于 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);
  },
});
相关推荐
保持学习ing1 小时前
帝可得 - 设备管理
javascript·vue.js·elementui
烛阴2 小时前
自动化测试、前后端mock数据量产利器:Chance.js深度教程
前端·javascript·后端
testleaf2 小时前
React知识点梳理
前端·react.js·typescript
每天都有好果汁吃2 小时前
基于 react-use 的 useIdle:业务场景下的用户空闲检测解决方案
前端·javascript·react.js
占星安啦3 小时前
一个html实现数据库自定义查询
java·前端·javascript·数据库·动态查询
老K(郭云开)3 小时前
allWebPlugin中间件VLC专用版之截图功能介绍
前端·javascript·chrome·中间件·edge
Rousson4 小时前
硬件学习笔记--65 MCU的RAM及FLash简介
开发语言·前端·javascript
萌萌哒草头将军4 小时前
🏖️ TanStack Router:搜索参数即状态!🚀🚀🚀
javascript·vue.js·react.js
小疯仔5 小时前
使用el-input数字校验,输入汉字之后校验取消不掉
android·开发语言·javascript
wangbing11256 小时前
开发指南120-表格(el-table)斑马纹
javascript·vue.js·elementui