前言
基于 uniapp 提供的 WebSocket Api 来进行封装,让你的 WebSocket 功能更加强大!
tip: 后续考虑做成 uniapp 插件,敬请期待。 🙏
实现思路
心跳检测
客户端定时向服务端发送"ping",如果服务端在一定的时间内,没有返回给客户端"pong",那么就判断为离线。
sequenceDiagram
participant 客户端
participant 服务端
客户端->>服务端: ping
服务端->>客户端: pong
断线重连
客户端监测到服务端断线后,就重新初始化 WebSocket 类,然后再进行检测,反复操作,直到连接成功为止。
代码实现
websocket.js
function pickJsonObj(value) {
try {
return JSON.parse(value)
} catch (e) {
return null;
}
}
class WebSocketClient {
constructor(url) {
this.url = url;
this.socket = null;
this.isReconnecting = false;
this.reconnectInterval = 3000; // 重连间隔,单位毫秒
this.heartBeatInterval = 5000; // 心跳间隔,单位毫秒
this.pingTimeoutDuration = 1000; // 超过这个时间,后端没有返回pong,则判定后端断线了。
this.heartBeatTimer = null;
this.destroy = false; // 是否销毁
}
connect() {
this.socket = uni.connectSocket({
url: this.url,
complete: () => {}
});
this.initEventListeners();
}
initEventListeners() {
this.socket.onOpen(() => {
// WebSocket连接已打开
this.onConnected();
this.startHeartBeat();
});
this.socket.onMessage((res) => {
const obj = pickJsonObj(res.data);
if (obj.type === 'pong') {
// 收到pong消息,心跳正常,无需处理
this.resetPingTimeout(); // 重置计时
} else {
// 处理其他消息
this.onMessage(res.data);
}
});
this.socket.onClose((res) => {
// WebSocket连接已关闭
if (this.destroy) {
this.onClosed()
return;
}
this.stopHeartBeat();
if (!this.isReconnecting) {
this.reconnect();
}
});
}
sendMessage(message) {
if (this.socket) {
this.socket.send({
data: message
});
}
}
onMessage(message) {
// 处理收到的消息
console.log('message:', message)
}
startHeartBeat() {
this.heartBeatTimer = setInterval(() => {
this.sendMessage(JSON.stringify({
type: 'ping'
})); // 发送ping消息
this.pingTimeout = setTimeout(() => {
// 未收到pong消息,尝试重连...
this.reconnect();
}, this.pingTimeoutDuration);
}, this.heartBeatInterval);
}
stopHeartBeat() {
if (this.heartBeatTimer) {
clearInterval(this.heartBeatTimer);
}
}
reconnect() {
this.isReconnecting = true;
setTimeout(() => {
this.onReconnect();
this.connect();
this.isReconnecting = false;
}, this.reconnectInterval);
}
resetPingTimeout() {
clearTimeout(this.pingTimeout); // 重置计时
}
close() {
this.destroy = true;
this.stopHeartBeat();
if (this.socket) {
this.socket.close();
this.socket = null;
}
}
/**
* 重连时触发
*/
onReconnect() {
console.log('尝试重连...')
}
/**
* 连接成功时触发
*/
onConnected() {
console.log('WebSocket连接已打开');
}
/**
* 断开时触发
*/
onClosed() {
console.log('已断开连接')
}
}
export default WebSocketClient;
使用示例
import WebSocketClient from '@/utils/websocket.js'
// 创建WebSocket实例
ws.value = new WebSocketClient('ws://这里填写你的服务地址');
// 连接WebSocket
ws.value.connect();
// 接收消息时触发
ws.value.onMessage = (value) => {
const obj = JSON.parse(value)
if (obj.type === 'message') {
list.value.push({
time: new Date().toLocaleString(),
value: obj.value
})
}
}
// 重连时触发
ws.value.onReconnect = () => {
netStatus.value = 2;
}
// 连接成功后触发
ws.value.onConnected = () => {
netStatus.value = 1;
}
// 关闭后触发(直接销毁了,不会继续重连)
ws.value.onClosed = () => {
netStatus.value = 0;
}
结语
希望对您有所帮助 😊