1. 创建websocket.js
// WebSocket 状态枚举
const WebSocketState = {
  CONNECTING: 0, // 连接中
  OPEN: 1,      // 已连接
  CLOSING: 2,   // 关闭中
  CLOSED: 3     // 已关闭
};

class WebSocketClient {
  /**
   * WebSocket客户端构造函数
   * @param {Object} config - 配置项
   * @param {string} config.url - WebSocket连接地址
   * @param {number} [config.pingInterval=5000] - 心跳间隔时间(ms)
   * @param {number} [config.reconnectAttempts=5] - 最大重连次数
   * @param {number} [config.reconnectInterval=3000] - 重连间隔时间(ms)
   */
  constructor(config) {
    this.socket = null;
    this.pingTimer = null;
    this.reconnectAttempts = 0;
    // 合并默认配置和用户配置
    this.config = {
      pingInterval: 5000,
      reconnectAttempts: 5,
      reconnectInterval: 3000,
      ...config
    };
    // 事件处理器映射表
    this.eventHandlers = new Map();
  }

  /**
   * 创建WebSocket连接
   */
  connect() {
    if (this.socket && this.socket.readyState === WebSocketState.OPEN) {
      console.log('WebSocket已经连接');
      return;
    }

    try {
      this.socket = new WebSocket(this.config.url);
      this.attachEventListeners();
    } catch (error) {
      console.error('WebSocket连接创建失败:', error);
      this.reconnect();
    }
  }

  /**
   * 绑定WebSocket事件监听器
   * @private
   */
  attachEventListeners() {
    if (!this.socket) return;

    // 连接成功回调
    this.socket.onopen = () => {
      console.log('WebSocket连接成功');
      this.reconnectAttempts = 0;
      this.startHeartbeat();
    };

    // 接收消息回调
    this.socket.onmessage = (event) => {
      this.handleMessage(event);
    };

    // 错误处理回调
    this.socket.onerror = (error) => {
      console.error('WebSocket错误:', error);
      this.reconnect();
    };

    // 连接关闭回调
    this.socket.onclose = () => {
      console.log('WebSocket连接关闭');
      this.cleanup();
      this.reconnect();
    };
  }

  /**
   * 处理接收到的消息
   * @private
   * @param {MessageEvent} event - WebSocket消息事件
   */
  handleMessage(event) {
    // 忽略心跳响应
    if (event.data === 'pong') return;

    try {
      const data = JSON.parse(event.data);
      // 触发所有注册的消息处理回调
      const handlers = this.eventHandlers.get('message') || [];
      handlers.forEach(callback => callback(data));
    } catch (error) {
      console.error('消息解析错误:', error);
    }
  }

  /**
   * 发送消息
   * @param {string[]} eventTypes - 事件类型数组
   */
  send(eventTypes) {
    if (!this.socket || this.socket.readyState !== WebSocketState.OPEN) {
      console.warn('WebSocket未连接,消息发送失败');
      return;
    }

    const message = {
      appId: 'airShip',
      cover: 0,
      event: eventTypes
    };

    try {
      this.socket.send(JSON.stringify(message));
    } catch (error) {
      console.error('消息发送失败:', error);
    }
  }

  /**
   * 开始心跳检测
   * @private
   */
  startHeartbeat() {
    this.stopHeartbeat();
    const ping = () => {
      if (this.socket?.readyState === WebSocketState.OPEN) {
        this.socket.send('ping');
      }
    };

    ping(); // 立即发送一次
    this.pingTimer = setInterval(ping, this.config.pingInterval);
  }

  /**
   * 停止心跳检测
   * @private
   */
  stopHeartbeat() {
    if (this.pingTimer) {
      clearInterval(this.pingTimer);
      this.pingTimer = null;
    }
  }

  /**
   * 重新连接
   * @private
   */
  reconnect() {
    if (this.reconnectAttempts >= this.config.reconnectAttempts) {
      console.error('WebSocket重连次数超过限制');
      return;
    }

    this.reconnectAttempts++;
    console.log(`尝试第${this.reconnectAttempts}次重连...`);
    
    setTimeout(() => {
      this.connect();
    }, this.config.reconnectInterval);
  }

  /**
   * 清理资源
   * @private
   */
  cleanup() {
    this.stopHeartbeat();
    if (this.socket) {
      this.socket.onopen = null;
      this.socket.onmessage = null;
      this.socket.onerror = null;
      this.socket.onclose = null;
    }
  }

  /**
   * 关闭WebSocket连接
   */
  close() {
    this.cleanup();
    if (this.socket) {
      this.socket.close();
      this.socket = null;
    }
  }

  /**
   * 添加事件监听器
   * @param {string} event - 事件名称
   * @param {Function} callback - 回调函数
   */
  on(event, callback) {
    const handlers = this.eventHandlers.get(event) || [];
    handlers.push(callback);
    this.eventHandlers.set(event, handlers);
  }

  /**
   * 移除事件监听器
   * @param {string} event - 事件名称
   * @param {Function} callback - 回调函数
   */
  off(event, callback) {
    const handlers = this.eventHandlers.get(event);
    if (handlers) {
      const index = handlers.indexOf(callback);
      if (index !== -1) {
        handlers.splice(index, 1);
      }
    }
  }
}

export default WebSocketClient;

  1. 组件中调用
import { onUnmounted } from 'vue';
import WebSocketClient from './websocket';

// 创建WebSocket实例
const wsClient = new WebSocketClient({
  url: 'wss://wss.xxxx.com/ws?appid=xxx',
  pingInterval: 5000,      // 5秒发送一次心跳
  reconnectAttempts: 5,    // 最多重连5次
  reconnectInterval: 3000  // 重连间隔3秒
});

// 连接WebSocket
wsClient.connect();

// 监听消息
wsClient.on('message', (data) => {
  console.log('收到消息:', data);
  // 在这里处理接收到的消息
});

// 发送消息
wsClient.send(['event1', 'event2']);

// 在组件卸载时关闭连接
onUnmounted(() => {
  wsClient.close();
}); 
Logo

前往低代码交流专区

更多推荐