WebSocket 模块实现与应用
WebSocket 技术是一种在 Web 开发中常用的实时通信方式,它允许客户端和服务器之间建立持久性的双向连接,以便实时地传输数据。在 Vue.js 项目中,使用 WebSocket 可以轻松实现实时消息推送、即时通讯等功能。在这篇博客中,我们将介绍一个基于 Vue.js 的 WebSocket 模块的实现,并讨论其功能、作用以及应用方式。
废话不多说,先提供代码
// 在 store 中创建一个模块(WebSocket 模块)
import {Notification} from 'element-ui';
import {getToken} from "@/utils/auth";
const state = {
ws: null,
heartCheckTimer: null,
};
const mutations = {
SET_WS(state, ws) {
state.ws = ws;
console.log("SET_WS", state.ws);
},
CLEAR_WS(state) {
state.ws = null;
},
SET_HEART_CHECK_TIMER(state, timer) {
state.heartCheckTimer = timer;
},
};
const actions = {
startWebSocket({commit, dispatch, state}) {
if (getToken() && (!state.ws || state.ws.readyState !== WebSocket.OPEN)) {
console.log("SOCKET_PATH:", process.env);
const socketUrl = `${process.env.VUE_APP_SOCKET_PATH}/ws?token=${getToken()}`;
const ws = new WebSocket(socketUrl);
ws.onmessage = function (e) {
console.log(`${new Date().toLocaleString()} >>>>> 收到消息 ${e.data}`, state.ws);
if (e.data !== "pong") {
Notification({
type: "info",
title: '新消息',
message: e.data,
position: "top-right",
duration: 3000,
showClose: true
});
}
};
ws.onclose = function () {
console.log(`${new Date().toLocaleString()} >>>>> 连接已关闭`);
// 尝试重新连接
dispatch('reconnectWebSocket');
};
ws.onopen = function () {
console.log(`${new Date().toLocaleString()} >>>>> 连接成功`, ws);
Notification({
type: "success",
title: '成功',
message: '会话连接成功',
position: "top-right",
duration: 3000,
showClose: true
});
// 保存 WebSocket 连接信息
commit('SET_WS', ws);
// // 在这里调用 sendWebSocketMessage,确保 state.ws 已经被正确设置
// 开始心跳检测
dispatch('startHeartCheck');
};
ws.onerror = function (e) {
console.log(`${new Date().toLocaleString()} >>>>> 数据传输发生异常`, e);
Notification({
type: "error",
title: '错误',
message: '会话连接异常,服务已断开',
position: "top-right",
duration: 3000,
showClose: true
});
};
}
},
sendWebSocketMessage({state}, msg) {
console.log(`${new Date().toLocaleString()} >>>>> 发送消息:${msg}`, state.ws);
state.ws.send(msg);
},
reconnectWebSocket({dispatch}) {
dispatch('clearWebSocket');
// 递归调用,一直尝试重连
setTimeout(() => {
dispatch('startWebSocket');
}, 6000);
},
clearWebSocket({commit, state}) {
if (state.ws) {
state.ws.close();
commit('CLEAR_WS');
}
},
startHeartCheck({commit, dispatch, state}) {
console.log(`${new Date().toLocaleString()} >>>>> 开始心跳检测`, state.ws);
// 清除之前的计时器
dispatch('clearHeartCheckTimer');
// 创建新的计时器
dispatch('sendWebSocketMessage', 'ping');
const timer = setInterval(() => {
if (!state.ws || state.ws.readyState !== WebSocket.OPEN) {
console.log(`${new Date().toLocaleString()} >>>>> 心跳检测失败,触发重连`, state.ws);
dispatch('reconnectWebSocket');
} else {
console.log(`${new Date().toLocaleString()} >>>>> 心跳正常,继续下一次心跳检测`, state.ws);
dispatch('sendWebSocketMessage', 'ping');
}
}, 1000 * 29);
commit('SET_HEART_CHECK_TIMER', timer);
},
clearHeartCheckTimer({commit, state}) {
const timer = state.heartCheckTimer;
timer && clearInterval(timer);
commit('SET_HEART_CHECK_TIMER', null);
},
};
export default {
state,
mutations,
actions,
};
1. 功能概述
该 WebSocket 模块提供了以下核心功能:
WebSocket 连接管理: 通过封装 WebSocket 的创建、连接、关闭等操作,实现了 WebSocket 连接的简便管理。
消息收发: 可以方便地发送和接收 WebSocket 消息,并在收到消息时进行相应的处理。
自动重连: 当 WebSocket 连接断开时,模块会自动尝试重新连接,确保持续的通信。
心跳检测: 集成了心跳检测机制,定期向服务器发送心跳消息,以确保连接的稳定性。
2. 代码结构
该模块的代码结构如下:
State: 维护了 WebSocket 连接对象(ws)和心跳检测定时器(heartCheckTimer)的状态。
Mutations: 提供了用于修改状态的同步方法,包括设置 WebSocket 对象、清除 WebSocket 对象以及设置心跳检测定时器。
Actions: 包含了异步的业务逻辑,如启动 WebSocket 连接、发送消息、重新连接、清除连接、启动心跳检测等。
3. 应用方式
3.1 安装模块
首先,确保你的项目中已经安装了 element-ui,因为在收到新消息时,会使用 element-ui 的 Notification 组件进行通知。
npm install element-ui
3.2 引入模块
在你的 Vuex store 中引入 WebSocket 模块:
// store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import webSocketModule from './modules/webSocket';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
webSocket: webSocketModule,
// other modules...
},
// other configurations...
});
3.3 启动 WebSocket 连接
在需要使用 WebSocket 的地方,通过 Vuex 的 Action 启动 WebSocket 连接:
export default {
mounted() {
this.$store.dispatch('startWebSocket');
},
}
3.4 发送和接收消息
通过 Vuex Action 可以方便地发送消息,同时通过监听 WebSocket 模块的状态来处理接收到的消息:
// YourComponent.vue
export default {
methods: {
sendMessage(message) {
this.$store.dispatch('sendWebSocketMessage', message);
},
},
computed: {
websocket() {
return this.$store.state.webSocket.ws;
},
},
watch: {
websocket(newVal) {
if (newVal) {
newVal.onmessage = (event) => {
// 处理接收到的消息
console.log('Received message:', event.data);
};
}
},
},
}
4. 使用过程中遇到的一些问题
4.1 页面刷新后socket连接断开,且不再重连
通常,在页面刷新时,WebSocket 连接会被断开,因为整个应用重新加载。为了解决这个问题,你可以考虑以下方案:
监听页面刷新事件: 在页面即将刷新或关闭时,可以通过监听 beforeunload 事件来执行一些清理操作,例如关闭 WebSocket 连接。这样可以确保在页面刷新或关闭时,WebSocket 连接得到正常关闭。
mounted() {
this.$nextTick(() => {
// 初始化 WebSocket 连接
this.$store.dispatch('startWebSocket');
// 在这里保存 this.$store 到一个变量
const store = this.$store;
// 在 beforeunload 事件中使用 store
window.addEventListener('beforeunload', function (event) {
store.dispatch('clearWebSocket');
// 在这里执行你的操作,例如保存数据
// const confirmationMessage = '确定要离开页面吗?';
// event.returnValue = confirmationMessage; // Standard for most browsers
// return confirmationMessage; // For some older browsers
});
})
}
代码放在App.vue下面的mouted即可
5. 总结
通过使用该 WebSocket 模块,我们可以轻松地在 Vue.js 项目中集成 WebSocket 功能,实现实时通信、消息推送等功能。模块的自动重连和心跳检测机制确保了连接的稳定性,而清晰的代码结构使得模块易于维护和扩展。在实际应用中,可以根据具体业务需求,结合 Vuex 状态管理和组件生命周期,灵活使用该模块,为项目提供更加强大的实时通信能力。
实际效果可查在线网站:https://web.yujky.cn
租户:体验租户
用户名:cxks
密码: cxks123