WebSocket单例模式实现与使用

发布于:2025-06-27 ⋅ 阅读:(20) ⋅ 点赞:(0)

提示:记录工作中遇到的需求及解决办法


前言

前端通过WebSocket的单例模式实现实时通信效果


提示:以下是本篇文章正文内容,下面案例可供参考

一、代码

export default class SocketService {
  /**
   * 单例实例
   */
  static instance = null;
  static get Instance() {
    if (!this.instance) {
      this.instance = new SocketService();
    }
    return this.instance;
  }

  // 连接状态标记
  isConnected = false;
  // 重试计数器
  reconnectCount = 0;
  // 最大重连次数
  maxReconnect = 5;
  // 重连延迟 (毫秒)
  reconnectDelay = 3000;
  // WebSocket 实例
  ws = null;
  // 消息回调函数映射表
  callbacks = new Map();

  /**
   * 初始化 WebSocket 连接
   * @param {string} url - WebSocket 服务器地址
   */
  connect(url) {
    if (this.ws) {
      this.disconnect();
    }

    this.ws = new WebSocket(url);

    // 连接成功
    this.ws.onopen = () => {
      this.isConnected = true;
      this.reconnectCount = 0;
      console.log("WebSocket connected");
    };

    // 接收消息
    this.ws.onmessage = (msg) => {
      try {
        const parsed = JSON.parse(msg.data);
        const { event, data } = parsed;
        
        // 触发对应事件回调
        if (this.callbacks.has(event)) {
          this.callbacks.get(event).forEach(cb => cb(data));
        }
      } catch (e) {
        console.error("Message parsing failed", e);
      }
    };

    // 连接关闭
    this.ws.onclose = () => {
      this.isConnected = false;
      console.log("WebSocket disconnected");
      
      // 自动重连逻辑
      if (this.reconnectCount < this.maxReconnect) {
        setTimeout(() => {
          console.log(`Reconnecting... (${this.reconnectCount + 1}/${this.maxReconnect})`);
          this.reconnectCount++;
          this.connect(url);
        }, this.reconnectDelay);
      }
    };

    // 错误处理
    this.ws.onerror = (err) => {
      console.error("WebSocket error:", err);
      this.ws.close();
    };
  }

  /**
   * 断开 WebSocket 连接
   */
  disconnect() {
    if (this.ws) {
      this.ws.close();
      this.ws = null;
      this.isConnected = false;
    }
  }

  /**
   * 注册事件监听器
   * @param {string} event - 事件名称
   * @param {Function} callback - 回调函数
   */
  on(event, callback) {
    if (!this.callbacks.has(event)) {
      this.callbacks.set(event, []);
    }
    this.callbacks.get(event).push(callback);
  }

  /**
   * 发送消息
   * @param {string} event - 事件类型
   * @param {Object} data - 发送数据
   */
  send(event, data) {
    if (this.isConnected) {
      const payload = JSON.stringify({ event, data });
      this.ws.send(payload);
    } else {
      console.error("Cannot send message - WebSocket not connected");
    }
  }

  /**
   * 移除事件监听器
   * @param {string} event - 事件名称
   * @param {Function} callback - 要移除的回调函数
   */
  off(event, callback) {
    if (this.callbacks.has(event)) {
      const callbacks = this.callbacks.get(event).filter(cb => cb !== callback);
      this.callbacks.set(event, callbacks);
    }
  }
}

// 使用示例:
// const socket = SocketService.Instance;
// socket.connect("wss://api.example.com");
// socket.on("message", (data) => console.log("Received:", data));
// socket.send("update", { value: 42 });

二、功能说明

  1. 单例模式:
    • 通过静态属性 instance 和静态方法 get Instance() 确保全局只有一个实例
    • 首次调用 SocketService.Instance 时自动创建实例
  2. 核心功能:
    • connect(url):建立 WebSocket 连接
    • disconnect():主动断开连接
    • on(event, callback):注册事件监听器
    • off(event, callback):移除事件监听器
    • send(event, data):发送结构化数据
  3. 自动重连机制:
    • 连接断开时自动尝试重连(最多 5 次)
    • 每次重连间隔 3 秒
    • 连接成功后重置重连计数器
  4. 消息协议:
    • 使用 JSON 格式:{ event: ‘事件名’, data: … }
    • 自动解析消息并触发对应事件回调

三、使用场景

// 在应用初始化时建立连接
const socket = SocketService.Instance;
socket.connect("wss://api.example.com/ws");

// 监听服务器消息
socket.on("chatMessage", (msg) => {
  console.log("New message:", msg);
});

// 发送数据
document.getElementById("sendBtn").addEventListener("click", () => {
  socket.send("userAction", { type: "click", count: 5 });
});

// 组件卸载时移除监听
const handler = (data) => { /* ... */ };
socket.on("update", handler);

// 需要时移除特定监听器
socket.off("update", handler);

此实现提供了完整的 WebSocket 连接管理,包括自动重连、事件订阅/发布机制,并严格遵循单例模式确保全局状态一致性。


网站公告

今日签到

点亮在社区的每一天
去签到