import { getToken } from '@/utils/auth'; import { checkLoginLine } from '@/api/login'; import { getBaseUrl } from '@/utils/baseUrl'; import { MessageBox } from 'element-ui'; import store from '@/store/index_APP_TARGET'; import SockJS from 'sockjs-client'; import Stomp from 'stompjs'; const isDev = process.env.NODE_ENV === 'development'; const isTest = process.env.NODE_ENV === 'test'; const websocketUrl = `${getBaseUrl()}/joylink-websocket?token=`; const reconnectInterval = [1000, 3000, 5000, 10000, 30000, 60000]; let notFirstConnect = false; var StompClient = function (headers) { this.url = websocketUrl + getToken(); this.headers = headers || {}; this.subscribeMap = new Map(); // 已订阅,对象{dest:'', handler:function, sub: Object} this.connect(); }; StompClient.prototype = { socket: null, clientIns: null, url: '', status: false, sockStatus: 0, headers: { // 'X-Token': getToken() }, isPassived:true, // 是否被动断线重连 // isconnect:true, count: 0, topic: '', onmessage: null, // 连接服务端 connect() { return new Promise((resolve, reject) => { try { // 建立连接对象(还未发起连接) // (null, {transports:['websocket']})虽可以解决连接关闭后xhr_streaming无限循环 // 但是该参数只会允许websockets,若不支持,直接报错 // 注意sockjs会做降级处理,优先处理websockets,若浏览器不支持websockets // 则会降级为xhr_streaming(轮询),继续不支持的时候会降级为xhr-polling this.socket = new SockJS(websocketUrl + getToken()); // 获取 STOMP 子协议的客户端对象 this.clientIns = Stomp.over(this.socket); this.closeStompDebug(); // const oldtransportClose = SockJS.prototype._transportClose; // SockJS.prototype._transportClose = function(code, reason) { // // To do // // ... // console.log(reason + '-----------------', this._transport); // if (this._transport && this._transport.close) { // this._transport.close(); // } // return oldtransportClose.call(this, code, reason); // }; // 向服务器发起websocket连接并发送CONNECT帧 this.websocketConnect(resolve); } catch (err) { reject(err); } }); }, websocketConnect(resolve) { const that = this; this.clientIns.connect({ 'X-Token': getToken() }, () => { if (notFirstConnect) { // setTimeout(()=>{ Message.success('连接成功'); }); } console.info('连接成功.'); that.count = 0; that.status = true; // 恢复订阅 that.subscribeMap.forEach((subscribe) => { that.subscribe(subscribe.dest, subscribe.handler); }); // sock断开回调 that.clientIns.ws.onclose = () => { // Message.error(`通信连接已断开!`); console.info(`通信连接已断开!`); notFirstConnect = true; checkLoginLine().then(() => { that.status = false; that.count++; that.reconnect(that.count, resolve); }).catch((err) => { that.logOut(err); }); }; resolve(this); }, () => { if (this.isPassived) { checkLoginLine().then(() => { this.count++; this.reconnect(this.count, resolve); }).catch((err) => { this.logOut(err); }); } }); }, logOut(err) { console.info(err); // 退出登陆前断开连接 store.dispatch('disconnect').then(()=>{ MessageBox.confirm('你已被登出,请重新登录', '确定登出', { confirmButtonText: '重新登录', showCancelButton: false, type: 'warning' }).then(() => { store.dispatch('FedLogOut').then(() => { location.reload();// 为了重新实例化vue-router对象 避免bug }); }); }); }, // 恢复链接 reconnect(count, resolve) { console.info(`尝试第${count || 1}次连接.`); // Message.warning(`正在尝试第${count || 1}次通讯连接。`); const that = this; setTimeout(() => { that.websocketConnect(resolve); }, reconnectInterval[that.count] || reconnectInterval[reconnectInterval.length - 1] ); }, closeStompDebug() { if (this.clientIns) { if (isDev || isTest) { this.clientIns.debug = function (message) { console.debug(message); }; } } }, // 订阅指定的topic subscribe(topic, onmessage, headers) { // const timeDelay = [1000, 2000, 5000, 10000]; this.topic = topic; this.onmessage = onmessage; this.headers = headers; if (!this.status) { this.subscribeMap.set(topic, {dest: topic, handler: onmessage, sub: null}); } else { const sub = this.clientIns.subscribe(topic, onmessage); this.subscribeMap.set(topic, {dest: topic, handler: onmessage, sub: sub}); } }, unsubscribe(topic) { const subscription = this.subscribeMap.get(topic); if (subscription && subscription.sub) { subscription.sub.unsubscribe(); this.subscribeMap.delete(topic); console.log('取消订阅:' + topic); } else if (subscription) { this.subscribeMap.delete(topic); } }, // 发送消息 send(url, msg) { if (this.status) { if (msg) { msg = JSON.stringify(msg); this.clientIns.send(url, {}, msg); } else { console.error('发送消息为空'); } } else { setTimeout(() => { this.send(url, msg); }, 300); } }, disconnect() { if (this.clientIns) { if (this.clientIns.connected) { this.clientIns.disconnect(); } this.isPassived = false; this.socket.close(); this.socket = null; this.clientIns = null; } this.status = false; console.info('断开连接'); } }; export default StompClient;