123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- /**
- * 骑手端WebSocket管理工具
- * 统一管理WebSocket连接、消息处理和状态维护
- *
- * @author kxmall
- * @date 2025-01-08
- */
- class RiderWebSocketManager {
- constructor() {
- this.websocket = null;
- this.heartbeatTimer = null;
- this.reconnectTimer = null;
- this.isManualClose = false; // 是否手动关闭
- this.reconnectAttempts = 0; // 重连尝试次数
- this.maxReconnectAttempts = 5; // 最大重连次数
- this.reconnectInterval = 5000; // 重连间隔
- this.heartbeatInterval = 30000; // 心跳间隔
-
- // 消息处理回调
- this.onMessageCallbacks = new Map();
- this.onStatusChangeCallback = null;
-
- // 绑定方法上下文
- this.connect = this.connect.bind(this);
- this.disconnect = this.disconnect.bind(this);
- this.send = this.send.bind(this);
- this.handleMessage = this.handleMessage.bind(this);
- }
- /**
- * 连接WebSocket
- * @param {Object} userInfo 用户信息
- * @param {String} baseUrl 基础URL
- */
- connect(userInfo, baseUrl) {
- if (!userInfo || !userInfo.id) {
- console.error('用户信息不存在,无法连接WebSocket');
- return;
- }
- if (this.websocket) {
- console.warn('WebSocket已存在,先断开再重连');
- this.disconnect();
- }
- // 构建WebSocket连接地址
- const socketUrl = `ws://${baseUrl.replace('http://', '').replace('https://', '')}/websocket/rider/${userInfo.id}`;
- console.log('连接WebSocket:', socketUrl);
- try {
- this.websocket = uni.connectSocket({
- url: socketUrl,
- success: () => {
- console.log('WebSocket连接请求发送成功');
- },
- fail: (err) => {
- console.error('WebSocket连接请求失败:', err);
- this._scheduleReconnect(userInfo, baseUrl);
- }
- });
- this._setupEventHandlers(userInfo, baseUrl);
-
- } catch (error) {
- console.error('创建WebSocket连接失败:', error);
- this._scheduleReconnect(userInfo, baseUrl);
- }
- }
- /**
- * 设置事件处理器
- * @private
- */
- _setupEventHandlers(userInfo, baseUrl) {
- if (!this.websocket) return;
- // 监听连接打开
- this.websocket.onOpen(() => {
- console.log('WebSocket连接已打开');
- this.reconnectAttempts = 0; // 重置重连次数
- this._startHeartbeat();
- this._notifyStatusChange('connected');
- });
- // 监听消息
- this.websocket.onMessage((res) => {
- console.log('收到WebSocket消息:', res.data);
- this.handleMessage(res.data);
- });
- // 监听错误
- this.websocket.onError((err) => {
- console.error('WebSocket发生错误:', err);
- this._notifyStatusChange('error', err);
- });
- // 监听关闭
- this.websocket.onClose((res) => {
- console.log('WebSocket连接关闭:', res);
- this._stopHeartbeat();
- this._notifyStatusChange('disconnected');
-
- // 如果不是手动关闭且用户仍然有效,则尝试重连
- if (!this.isManualClose && userInfo && userInfo.state) {
- this._scheduleReconnect(userInfo, baseUrl);
- }
- });
- }
- /**
- * 断开WebSocket连接
- */
- disconnect() {
- this.isManualClose = true;
- this._stopHeartbeat();
- this._stopReconnect();
-
- if (this.websocket) {
- this.websocket.close();
- this.websocket = null;
- }
-
- console.log('WebSocket手动断开');
- this._notifyStatusChange('disconnected');
- }
- /**
- * 发送消息
- * @param {String} message 消息内容
- */
- send(message) {
- if (!this.websocket) {
- console.warn('WebSocket未连接,无法发送消息');
- return false;
- }
- this.websocket.send({
- data: message,
- success: () => {
- console.log('WebSocket消息发送成功:', message);
- },
- fail: (err) => {
- console.error('WebSocket消息发送失败:', err);
- }
- });
- return true;
- }
- /**
- * 处理接收到的消息
- * @param {String} data 消息数据
- */
- handleMessage(data) {
- try {
- // 处理心跳响应
- if (data === '连接成功' || data === 'pong') {
- return;
- }
- // 解析JSON消息
- const message = typeof data === 'string' ? JSON.parse(data) : data;
-
- // 调用对应的消息处理回调
- const callback = this.onMessageCallbacks.get(message.type);
- if (callback && typeof callback === 'function') {
- callback(message);
- } else {
- console.warn('未找到消息类型处理器:', message.type);
- }
-
- } catch (error) {
- console.error('处理WebSocket消息失败:', error);
- }
- }
- /**
- * 注册消息处理回调
- * @param {String} messageType 消息类型
- * @param {Function} callback 回调函数
- */
- onMessage(messageType, callback) {
- this.onMessageCallbacks.set(messageType, callback);
- }
- /**
- * 注册状态变化回调
- * @param {Function} callback 回调函数
- */
- onStatusChange(callback) {
- this.onStatusChangeCallback = callback;
- }
- /**
- * 移除消息处理回调
- * @param {String} messageType 消息类型
- */
- offMessage(messageType) {
- this.onMessageCallbacks.delete(messageType);
- }
- /**
- * 清除所有回调
- */
- clearCallbacks() {
- this.onMessageCallbacks.clear();
- this.onStatusChangeCallback = null;
- }
- /**
- * 获取连接状态
- */
- isConnected() {
- return this.websocket !== null;
- }
- /**
- * 开始心跳
- * @private
- */
- _startHeartbeat() {
- this._stopHeartbeat();
- this.heartbeatTimer = setInterval(() => {
- this.send('ping');
- }, this.heartbeatInterval);
- }
- /**
- * 停止心跳
- * @private
- */
- _stopHeartbeat() {
- if (this.heartbeatTimer) {
- clearInterval(this.heartbeatTimer);
- this.heartbeatTimer = null;
- }
- }
- /**
- * 计划重连
- * @private
- */
- _scheduleReconnect(userInfo, baseUrl) {
- if (this.isManualClose || this.reconnectAttempts >= this.maxReconnectAttempts) {
- console.log('不再尝试重连');
- return;
- }
- this._stopReconnect();
-
- this.reconnectAttempts++;
- const delay = this.reconnectInterval * this.reconnectAttempts;
-
- console.log(`${delay/1000}秒后尝试第${this.reconnectAttempts}次重连`);
-
- this.reconnectTimer = setTimeout(() => {
- console.log(`开始第${this.reconnectAttempts}次重连`);
- this.connect(userInfo, baseUrl);
- }, delay);
- }
- /**
- * 停止重连
- * @private
- */
- _stopReconnect() {
- if (this.reconnectTimer) {
- clearTimeout(this.reconnectTimer);
- this.reconnectTimer = null;
- }
- }
- /**
- * 通知状态变化
- * @private
- */
- _notifyStatusChange(status, data = null) {
- if (this.onStatusChangeCallback && typeof this.onStatusChangeCallback === 'function') {
- this.onStatusChangeCallback(status, data);
- }
- }
- /**
- * 重置连接状态(用于手动重连)
- */
- reset() {
- this.isManualClose = false;
- this.reconnectAttempts = 0;
- }
- /**
- * 销毁实例
- */
- destroy() {
- this.disconnect();
- this.clearCallbacks();
- this._stopReconnect();
- }
- }
- // 消息类型常量
- export const MESSAGE_TYPES = {
- NEW_ORDER: 'NEW_ORDER',
- ORDER_CANCEL: 'ORDER_CANCEL',
- ORDER_STATUS_UPDATE: 'ORDER_STATUS_UPDATE',
- SYSTEM_MESSAGE: 'SYSTEM_MESSAGE'
- };
- // 连接状态常量
- export const CONNECTION_STATUS = {
- CONNECTING: 'connecting',
- CONNECTED: 'connected',
- DISCONNECTED: 'disconnected',
- ERROR: 'error'
- };
- // 导出单例实例
- const riderWebSocketManager = new RiderWebSocketManager();
- export default riderWebSocketManager;
|