From 63cd08ccf62c83cc7f1d600f3678baf4405bb74b Mon Sep 17 00:00:00 2001 From: fan <18706759286@163.com> Date: Tue, 14 Jan 2020 14:03:56 +0800 Subject: [PATCH] socket --- src/utils/sockNew.js | 213 +++++++++++++++++++++++++++++++++++++++ src/utils/stompClient.js | 87 ++++++++++++++++ 2 files changed, 300 insertions(+) create mode 100644 src/utils/sockNew.js create mode 100644 src/utils/stompClient.js diff --git a/src/utils/sockNew.js b/src/utils/sockNew.js new file mode 100644 index 000000000..09457e458 --- /dev/null +++ b/src/utils/sockNew.js @@ -0,0 +1,213 @@ +import { getToken } from '@/utils/auth'; +import { checkLoginLine } from '@/api/login'; +import { getBaseUrl } from '@/utils/baseUrl'; +import { MessageBox } from 'element-ui'; +import store from '../store'; +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=`; + +var StompClient = function (headers) { + this.url = websocketUrl + getToken(); + this.headers = headers || {}; + this.connect(); +}; + +StompClient.prototype = { + socket: null, + + clientIns: null, + + subscribeMap: null, + + url: '', + + status: false, + + sockStatus: 0, + + headers: { + // 'X-Token': getToken() + }, + + count: 0, + + topic: '', + + onmessage: 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 + getToken()); + + // 获取 STOMP 子协议的客户端对象 + this.clientIns = Stomp.over(this.socket); + + this.closeStompDebug(); + + // 向服务器发起websocket连接并发送CONNECT帧 + this.clientIns.connect({ 'X-Token': getToken() }, () => { + 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 = () => { + checkLoginLine().then(() => { + this.status = false; + this.count++; + this.reconnect(this.count); + }).catch((err) => { + this.logOut(err); + }); + }; + } + resolve(this); + }, () => { + checkLoginLine().then(() => { + this.connect(); + }).catch((err) => { + if (err.code == 40003 || err.code == 40004 || err.code == 40005 || err.code == 50012) { + this.logOut(); + } + if (err.code == 50008 || err.code == 50014) { + this.url = websocketUrl + getToken(); + this.connect(); + } + }); + }); + } catch (err) { + reject(err); + } + }); + + }, + logOut(err) { + if (err.code == 40003 || err.code == 40004 || err.code == 40005 || err.code == 50012) { + MessageBox.confirm('你已被登出,请重新登录', '确定登出', { + confirmButtonText: '重新登录', + showCancelButton: false, + type: 'warning' + }).then(() => { + store.dispatch('FedLogOut').then(() => { + location.reload();// 为了重新实例化vue-router对象 避免bug + }); + }); + } + if (err.code == 50008 || err.code == 50014) { + this.url = websocketUrl + getToken(); + this.status = false; + this.count++; + this.reconnect(this.count); + } + }, + // 恢复链接 + 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 || isTest) { + 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) { + if (msg) { + msg = JSON.stringify(msg); + } + 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.clientIns && this.clientIns.connected) { + this.clientIns.disconnect(); + this.clientIns = null; + } + this.status = false; + console.log('断开连接'); + } + +}; + +export default StompClient; diff --git a/src/utils/stompClient.js b/src/utils/stompClient.js new file mode 100644 index 000000000..bf837b629 --- /dev/null +++ b/src/utils/stompClient.js @@ -0,0 +1,87 @@ +import SockJS from 'sockjs-client'; +import Stomp from 'stompjs'; +import { getBaseUrl } from '@/utils/baseUrl'; + +const BASE_API = getBaseUrl(); +let baseUrl = "http://192.168.3.6:9600";//本地旭强 +if(BASE_API == 'https://joylink.club/jlcloud'){ + baseUrl = "https://joylink.club/relay"; +}else if(BASE_API == 'https://test.joylink.club/jlcloud'){ + baseUrl = "https://test.joylink.club/relay"; +} + +class StompClient { + + constructor() { + const ws = new SockJS(`${baseUrl}/ws-relay`); + this.client = Stomp.over(ws); + this.client.debug = function (message) { + console.debug(message); + }; + this.subscribeMap = new Map(); // 已订阅,对象{dest:'', handler:function, sub: Object} + this.connected = false; + this.onUsed = false; + } + + connect() { + return new Promise((resolve, reject) => { + this.onUsed = true; + const that = this; + const header = { + login: 'relay', + passcode: 'relay' + }; + this.client.connect(header, + ()=>{ + that.connected = true; + // 重连时需要重新订阅 + that.subscribeMap.forEach((subscribe, dest) => { + that.subscribe(subscribe.dest, subscribe.handler); + }); + resolve(); + }, + (error)=>{ + console.error(error); + this.connected = false; + reject(error); + }); + }); + } + + disconnect() { + this.onUsed = false; + this.client.disconnect(); + } + + subscribe(destination, handler) { + if (!this.connected) { + const that = this; + this.connect().then(() => { + that.subscribe(destination, handler); + }); + } else { + const sub = this.client.subscribe(destination, handler); + this.subscribeMap.set(destination, {dest: destination, handler: handler, sub: sub}); + } + } + + unsubscribe(destination) { + const subscribe = this.subscribeMap.get(destination); + if (subscribe && subscribe.sub) { + subscribe.sub.unsubscribe(); + } else if (subscribe) { + this.subscribeMap.delete(destination); + } + } + + send(destination, body) { + if (body) { + body = JSON.stringify(body); + this.client.send(destination, {}, body); + } else { + console.error('stomp send body required'); + } + } +} + +export default StompClient;