后端篇: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
}