自用基于 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);
  },
});
相关推荐
走粥1 天前
选项式API与组合式API的区别
开发语言·前端·javascript·vue.js·前端框架
We་ct1 天前
LeetCode 12. 整数转罗马数字:从逐位实现到规则复用优化
前端·算法·leetcode·typescript
晚霞的不甘1 天前
解决 Flutter for OpenHarmony 构建失败:HVigor ERROR 00303168 (SDK component missing)
android·javascript·flutter
2501_944521591 天前
Flutter for OpenHarmony 微动漫App实战:分享功能实现
android·开发语言·javascript·flutter·ecmascript
小小码农Come on1 天前
QPushButton QSS(一):按钮常用qss
前端·javascript·css·qt5
Booksort1 天前
React+js环境配置(极速版)
前端·javascript·react.js
mjr1 天前
基于Netty的WebSocket实时消息推送系统
网络·websocket·网络协议
幻云20101 天前
Next.js 之道:从入门到精通
前端·javascript·vue.js·人工智能·python
2501_944521591 天前
Flutter for OpenHarmony 微动漫App实战:标签筛选功能实现
android·开发语言·前端·javascript·flutter
EndingCoder1 天前
构建工具集成:Webpack 和 TypeScript
前端·webpack·typescript