123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- // websocket.js
- // 封装一个兼容多端的 uniapp WebSocket 管理类,支持自动重连与心跳机制,便于在uni-app项目中统一管理WebSocket连接
- class UniWebSocket {
- /**
- * 构造函数,初始化WebSocket管理器
- * @param {string} url - WebSocket服务器地址
- * @param {object} options - 可选配置项,如最大重连次数、心跳间隔等
- */
- constructor(url, options = {}) {
- this.url = url; // WebSocket服务器地址
- this.options = options; // 连接配置参数
- this.socketTask = null; // uni.connectSocket返回的socket任务对象
- this.isConnected = false; // 当前连接状态
- this.reconnectCount = 0; // 当前已重连次数
- this.maxReconnect = options.maxReconnect || 5; // 最大重连次数,默认5次
- this.heartbeatInterval = options.heartbeatInterval || 30000; // 心跳包发送间隔,默认30秒
- this.heartbeatTimer = null; // 心跳定时器
- this.eventListeners = {
- open: [], // 连接打开事件监听器
- message: [], // 消息接收事件监听器
- error: [], // 错误事件监听器
- close: [] // 关闭事件监听器
- };
- this.manualClose = false; // 是否为手动关闭连接
- }
- /**
- * 建立WebSocket连接
- * 若已连接则不重复连接
- */
- connect() {
- if (this.isConnected) return;
- this.manualClose = false;
- this.socketTask = uni.connectSocket({
- url: this.url,
- ...this.options
- });
- this._initEvent(); // 初始化事件监听
- }
- /**
- * 初始化WebSocket事件监听(open、message、error、close)
- * 绑定到socketTask对象
- * @private
- */
- _initEvent() {
- // 连接成功事件
- this.socketTask.onOpen = (res) => {
- this.isConnected = true;
- this.reconnectCount = 0;
- this._emit('open', res);
- this._startHeartbeat(); // 启动心跳
- };
- // 接收到消息事件
- this.socketTask.onMessage = (res) => {
- this._emit('message', res);
- this._startHeartbeat(); // 收到消息后重置心跳
- };
- // 连接错误事件
- this.socketTask.onError = (err) => {
- this._emit('error', err);
- this._reconnect(); // 尝试重连
- };
- // 连接关闭事件
- this.socketTask.onClose = (res) => {
- this.isConnected = false;
- this._emit('close', res);
- this._stopHeartbeat(); // 停止心跳
- if (!this.manualClose) {
- this._reconnect(); // 非手动关闭时自动重连
- }
- };
- }
- /**
- * 发送消息到WebSocket服务器
- * @param {string|object} data - 要发送的数据,支持字符串或对象
- * @returns {Promise} - 发送成功/失败的Promise
- */
- send(data) {
- return new Promise((resolve, reject) => {
- if (!this.isConnected) {
- reject('WebSocket 未连接');
- return;
- }
- this.socketTask.send({
- data: typeof data === 'string' ? data : JSON.stringify(data),
- success: resolve,
- fail: reject
- });
- });
- }
- /**
- * 主动关闭WebSocket连接
- * @param {number} code - 关闭码,默认1000
- * @param {string} reason - 关闭原因
- */
- close(code = 1000, reason = '') {
- this.manualClose = true;
- if (this.socketTask) {
- this.socketTask.close({ code, reason });
- }
- this._stopHeartbeat();
- }
- /**
- * 注册事件监听器
- * @param {string} event - 事件名(open/message/error/close)
- * @param {function} callback - 回调函数
- */
- on(event, callback) {
- if (this.eventListeners[event]) {
- this.eventListeners[event].push(callback);
- }
- }
- /**
- * 移除事件监听器
- * @param {string} event - 事件名
- * @param {function} callback - 需移除的回调函数
- */
- off(event, callback) {
- if (this.eventListeners[event]) {
- this.eventListeners[event] = this.eventListeners[event].filter(fn => fn !== callback);
- }
- }
- /**
- * 触发事件,调用所有注册的监听器
- * @param {string} event - 事件名
- * @param {any} data - 事件数据
- * @private
- */
- _emit(event, data) {
- if (this.eventListeners[event]) {
- this.eventListeners[event].forEach(fn => fn(data));
- }
- }
- /**
- * 自动重连逻辑,递增重连次数,超出最大次数则停止
- * @private
- */
- _reconnect() {
- if (this.reconnectCount < this.maxReconnect) {
- this.reconnectCount++;
- setTimeout(() => {
- this.connect();
- }, 1000 * this.reconnectCount); // 重连间隔递增
- }
- }
- /**
- * 启动心跳机制,定时发送ping包保持连接活跃
- * @private
- */
- _startHeartbeat() {
- this._stopHeartbeat();
- if (this.heartbeatInterval > 0) {
- this.heartbeatTimer = setInterval(() => {
- if (this.isConnected) {
- this.send('ping').catch(() => {});
- }
- }, this.heartbeatInterval);
- }
- }
- /**
- * 停止心跳机制
- * @private
- */
- _stopHeartbeat() {
- if (this.heartbeatTimer) {
- clearInterval(this.heartbeatTimer);
- this.heartbeatTimer = null;
- }
- }
- }
- export default UniWebSocket;
|