本文将详细介绍如何在UniApp项目中对接WebSocket进行实时通信,并使用Vuex管理WebSocket消息的状态。通过封装uni原生的WebSocket API,创建一个工具类`websocket.js`,并在应用启动时初始化WebSocket连接,确保能够实时监听和更新页面。
1. 封装uni原生的WebSocket,写出工具类`websocket.js`
2. 下载Vuex,并在`main.js`中添加Vuex store,并在应用实例化时初始化WebSocket连接
1、封装uni原生的WebSocket
首先,我们需要封装uni原生的WebSocket API,以便在项目中方便地使用WebSocket功能。我们将创建一个工具类`websocket.js`来管理WebSocket实例及其相关方法。
// websocket.js
// 基础消息模板
const socketMessageTemplate = {
type: "", // 消息类型
timestamp: null, // 时间戳
data: null, // 数据
from: "", // 发送者
to: "", // 接收者
msg: "", // 消息内容
};
// WebSocket 管理类
class WebSocketManager {
constructor({
// 最大重连次数
maxReconnectAttempts = 6,
// 重连间隔(毫秒)
reconnectInterval = 60000,
// 心跳间隔(毫秒)
heartbeatInterval = 60000,
} = {}) {
this.socket = null; // WebSocket 实例
this.listeners = {}; // 事件监听器
this.status = "closed"; // 连接状态:closed, connecting, connected
this.heartbeatTimer = null; // 心跳定时器
this.reconnectAttempts = 0; // 当前重连次数
this.maxReconnectAttempts = maxReconnectAttempts; // 最大重连次数
this.reconnectInterval = reconnectInterval; // 重连间隔(毫秒)
this.heartbeatInterval = heartbeatInterval; // 心跳间隔(毫秒)
this.url = null; // WebSocket 地址
this.isManualClose = false; // 是否为用户主动关闭
}
/**
* 连接 WebSocket
* @param {string} url WebSocket 地址
* @param {function} successCallback 连接成功回调函数
*/
connect(url, successCallback = () => { }) {
if (!url) {
console.error("WebSocket 地址不能为空");
return;
}
/* if (this.status === "connecting") {
console.warn("WebSocket 正在连接中,请稍后再试");
return;
} */
if (this.status === "connected") {
console.warn("WebSocket 已连接,请勿重复连接");
return;
}
this.url = url;
this.status = "connecting";
this.isManualClose = false; // 重置手动关闭标志
this.socket = uni.connectSocket({
url,
success: () => {
successCallback();
console.log("WebSocket 连接请求已发送");
},
fail: (error) => {
console.error("WebSocket 连接失败", error);
this.status = "closed";
this.handleReconnect();
},
});
this.initEventHandlers();
}
/**
* 初始化 WebSocket 事件
*/
initEventHandlers() {
uni.onSocketOpen(() => {
if (this.status === "connected") return; // 避免重复发送初始化消息
this.status = "connected";
this.reconnectAttempts = 0;
this.startHeartbeat();
this.triggerEvent("open");
});
uni.onSocketMessage(({ data }) => {
try {
console.log("消息解析111", data);
// const message = JSON.parse(decodeURIComponent(data));
const message = JSON.parse(data);
console.log("消息解析websoket22222222", message);
store.commit('ADD_MESSAGE',message.category);
} catch (err) {
// console.error("消息解析失败", err);
}
});
uni.onSocketError((err) => {
console.error("WebSocket 错误", err);
this.triggerEvent("error", err);
});
uni.onSocketClose(() => {
this.status = "closed";
this.stopHeartbeat();
this.triggerEvent("close");
if (!this.isManualClose) {
this.handleReconnect();
}
});
}
/**
* 处理重连逻辑
*/
handleReconnect() {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
console.log(`尝试第 ${this.reconnectAttempts} 次重连...`);
this.status = "connecting";
setTimeout(() => this.connect(this.url), this.reconnectInterval);
} else {
this.status = "fail";
console.error("重连次数已达上限,停止重连");
}
}
/**
* 启动心跳机制
*/
startHeartbeat() {
this.stopHeartbeat(); // 避免重复启动
this.heartbeatTimer = setInterval(() => {
if (this.status ==