后端篇:https://lux-sun.blog.csdn.net/article/details/101352493
前端篇
1、在 main.js 里赋值给 this
// main.js import websocket from '@/assets/js/websocket' Vue.prototype.websocket = websocket
2、 在首页 mounted 钩子函数里开启长连接
// index.vue mounted () { this.websocket.initWebSocket() // 开启长连接 }
3、所有的业务都在这里处理,无需其它地方再调用 websocket.js 里的函数
// websocket.js import cookie from '@/assets/js/cookieUtil' import store from '@/store' import { Notification } from 'element-ui' import goodorder from '@/api/goodorderBG' let websocketURL = 'wss://xxx/websocket' let heartbeatTime = 20000 // nginx 60s 限制,这里 20s 一次心跳 let reconnectionTime = 10000 // 断线后 10s 尝试一次重连 let ws = null let that = null let reconnection = true let reconnectionCount = 0 export default { initWebSocket(){ console.log('初始化websocket'); that = this if(ws!==null){ this.closeWebsocket() } ws = new WebSocket(websocketURL); ws.onmessage = this.websocketOnMessage; ws.onopen = this.websocketOnOpen; ws.onerror = this.websocketOnError; ws.onclose = this.websocketClose; }, websocketOnOpen(){ // 连接建立之后执行send方法发送数据 Notification({ title: '已连接到服务器', message: '成功与服务器建立联机', type: 'success', offset: 60 // 偏移量 }) reconnectionCount = 0 let account = JSON.parse(cookie.getCookie()) let actions = {"operand":1, "userId":account.userInfo.userId} that.websocketSend(JSON.stringify(actions)) // 绑定userId that.initData() // 初始化websocket建立数据 }, websocketOnError(){ // 连接建立失败重连 }, websocketOnMessage(e){ // 数据接收 let data = JSON.parse(e.data) if(data.status === 1){ // 1:连接无异常 setTimeout(() => { that.heartbeat() },heartbeatTime) // 心跳包 }else if(data.status === 2) { // 2:有新的业务逻辑消息需要处理 let info = JSON.parse(data.data) if(info.type === 1){ // 家长申请订单 store.dispatch('websocket/changeAuditOrderNum',info.data.total) Notification({ title: '您的家长申请订单数量有新的变化', message: data.msg, offset: 60 }); } } }, websocketSend(data){ // 数据发送 ws.send(data); }, websocketClose(e){ // 关闭 if(reconnection){ if(reconnectionCount === 0){ Notification({ title: '连接意外断开', message: '正在尝试重新建立连接', type: 'error', offset: 60 }) } setTimeout(() => { console.log('尝试重连') reconnectionCount += 1 that.initWebSocket() },reconnectionTime) // 重新连接 }else{ // 不重连但是将重连状态改为true console.log('停止连接') reconnection = true } }, closeWebsocket(){ // 主动关闭websocket try { ws.close() ws = null }catch (e) { } }, heartbeat(){ let actions = {"operand":2}; this.websocketSend(JSON.stringify(actions)); }, setReconnection(rc){ // 退出登录会调用,且设置false reconnection = rc }, initData(){ // 获取申请订单数 goodorder.getTempGoodorderCount( { status: 0, type: 0 } ).then(res => { if(res.success){ store.dispatch('websocket/changeAuditOrderNum',res.data) } else if (res.nullwarn) { store.dispatch('websocket/changeAuditOrderNum',0) } else { this.$message({ type: 'error', message: res.msg }) } }).catch(error => { if(error !== 'noLogin'){ this.$message({ type: 'error', message: '系统错误' }) } }) } }
4、这里用到了 Vuex,我们稍微看下
// store/index.js import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const modulesFiles = require.context('./modules', false, /\.js$/) const modules = modulesFiles.keys().reduce((modules, modulePath) => { // set './app.js' => 'app' const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1') const value = modulesFiles(modulePath) modules[moduleName] = value.default return modules }, {}) const store = new Vuex.Store({ modules }) export default store
// store/modules/websocket.js const state = { tempOrderNum: 0, noticeNum: 0 } const mutations = { changeTempOrderNum: (state,num) => { state.tempOrderNum = num state.noticeNum = state.tempOrderNum } } const actions = { changeTempOrderNum({ commit },num) { commit('changeTempOrderNum',num) } } export default { namespaced: true, state, mutations, actions }