import { handleToken } from '@/utils/auth'; import { checkLoginLine } from '@/api/login'; import { getBaseUrl } from '@/utils/baseUrl'; var SockJS = require('sockjs-client'); var Stomp = require('stompjs'); const isDev = process.env.NODE_ENV === 'development'; const websocketUrl = `${getBaseUrl()}/joylink-websocket?token=`; // const websocketUrl = `http://192.168.3.6:9000/joylink-websocket?token=`; var StompClient = function (headers) { this.url = websocketUrl + handleToken(); this.headers = headers || {}; this.connect(); }; StompClient.prototype = { socket: null, clientIns: null, subscribeMap: null, url: '', status: false, sockStatus: 0, headers: { 'X-Token': handleToken() }, count: 0, topic: '', onmessage: null, checkTimer: null, // 连接服务端 connect() { return new Promise((resolve, reject) => { try { // 断开已有连接 if (this.clientIns && this.clientIns.connected) { this.clientIns.disconnect(); this.clientIns = null; } // 建立连接对象(还未发起连接) this.socket = new SockJS(websocketUrl + handleToken()); // 获取 STOMP 子协议的客户端对象 this.clientIns = Stomp.over(this.socket); this.closeStompDebug(); // 向服务器发起websocket连接并发送CONNECT帧 this.clientIns.connect({ 'X-Token': handleToken() }, () => { console.info('连接成功.'); this.count = 0; this.status = true; // 恢复订阅 if (this.topic && this.onmessage) { this.unsubscribe(this.topic); this.subscribe(this.topic, this.onmessage, this.headers); } // 检测sock是否断开 if (!this.clientIns.ws.onclose) { this.clientIns.ws.onclose = () => { console.info('检测到socket断开!'); this.status = false; this.count++; this.reconnect(this.count); }; } // 定时器检测网络 if (!this.checkTimer) { this.checkTimer = setInterval(() => { if (!this.status || !this.clientIns.ws.onclose) { // 发送检测心跳,如果失败则在如下情况时需要断开WebSocket; // 40003/40004/40005: 登陆过期; // 50008: 非法的token; // 50012: 其他客户端登录了; // 50014: Token 过期了; checkLoginLine().then(() => { // 会有连接延时,需要多次判断 // 如果socket或着clientIns断开,则重新连接 if (!this.status || !this.clientIns.ws.onclose) { this.count++; this.reconnect(this.count); } }).catch((err) => { if (err.code == 40003 || err.code == 40004 || err.code == 40005 || err.code == 50008 || err.code == 50012 || err.code == 50014) { this.status = false; this.count++; this.reconnect(this.count); } }); } }, 30000); } resolve(this); }, () => { this.connect(); }); } catch (err) { reject(err); } }); }, // 恢复链接 reconnect(count) { console.info(`尝试第${count || 1}次连接.`); this.connect().then(() => { }).catch(() => { this.count++; this.reconnect(this.count); }); }, closeStompDebug() { if (this.clientIns) { this.clientIns.debug = undefined; if (isDev) { this.clientIns.debug = function (message) { console.debug(message); }; } } }, // 订阅指定的topic subscribe(topic, onmessage, headers) { this.topic = topic; this.onmessage = onmessage; this.headers = headers; if (this.status) { if (!this.subscribeMap) { this.subscribeMap = new Map(); } try { var subscription = this.subscribeMap.get(topic); if (!subscription) { subscription = this.clientIns.subscribe(topic, onmessage, headers); // 接收消息通过 subscribe() 方法实现 this.subscribeMap.set(topic, subscription); } } catch (err) { setTimeout(() => { this.subscribe(topic, onmessage, headers); }, 300); } } else { setTimeout(() => { this.subscribe(topic, onmessage, headers); }, 300); } }, unsubscribe(topic) { if (this.subscribeMap) { const subscription = this.subscribeMap.get(topic); if (subscription) { subscription.unsubscribe(); this.subscribeMap.delete(topic); console.log('取消订阅'); } } }, // 发送消息 send(url, msg) { if (this.status) { try { this.clientIns.send(url, {}, msg); } catch (err) { this.status = false; this.send(url, msg); } } else { setTimeout(() => { this.send(url, msg); }, 300); } }, disconnect() { if (this.checkTimer) { clearInterval(this.checkTimer); this.checkTimer = null; } if (this.clientIns && this.clientIns.connected) { this.clientIns.disconnect(); this.clientIns = null; } this.status = false; console.log('断开连接'); } }; export default StompClient;