一、前言
在如今的移动应用开发领域,实时通信的重要性不言而喻。WebSocket 凭借其在单个 TCP 连接上实现全双工通信的特性,成为实现实时数据传输的理想选择。UniApp 作为一款强大的跨平台开发框架,支持使用 Vue.js 语法编写一次代码并发布到多个平台。本文将详细阐述如何在 UniApp 中封装 WebSocket,并且加入重连机制,确保在连接断开时能自动尝试重新连接,以保障实时通信的稳定性。
二、创建带重连机制的 WebSocket 封装类
1. 创建封装文件
在 UniApp 项目的 utils
目录下创建 websocket.js
文件,用于封装 WebSocket 相关操作,同时添加重连逻辑。
// utils/websocket.js
export default class WebSocketUtil {
constructor(url, reconnectInterval = 5000, maxReconnectAttempts = 10) {
this.url = url;
this.websocket = null;
this.callbacks = {};
this.reconnectInterval = reconnectInterval;
this.maxReconnectAttempts = maxReconnectAttempts;
this.reconnectAttempts = 0;
this.reconnectTimer = null;
}
connect() {
return new Promise((resolve, reject) => {
if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
resolve(this.websocket);
return;
}
this.websocket = uni.connectSocket({
url: this.url,
success: (res) => {
console.log('WebSocket 连接成功', res);
this.reconnectAttempts = 0;
resolve(this.websocket);
},
fail: (err) => {
console.error('WebSocket 连接失败', err);
this.tryReconnect();
reject(err);
}
});
this.setupEventListeners();
});
}
setupEventListeners() {
this.websocket.onOpen(() => {
console.log('WebSocket 已打开');
this.reconnectAttempts = 0;
clearInterval(this.reconnectTimer);
});
this.websocket.onError((err) => {
console.error('WebSocket 发生错误', err);
this.tryReconnect();
});
this.websocket.onClose(() => {
console.log('WebSocket 已关闭');
this.tryReconnect();
});
this.websocket.onMessage((res) => {
const data = JSON.parse(res.data);
if (this.callbacks[data.type]) {
this.callbacks[data.type](data);
}
});
}
tryReconnect() {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
console.log(`尝试第 ${this.reconnectAttempts} 次重连...`);
this.reconnectTimer = setTimeout(() => {
this.connect();
}, this.reconnectInterval);
} else {
console.error('达到最大重连次数,停止重连');
}
}
send(data) {
if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
this.websocket.send({
data: JSON.stringify(data)
});
} else {
console.error('WebSocket 未连接,无法发送数据');
}
}
on(eventType, callback) {
this.callbacks[eventType] = callback;
}
close() {
clearInterval(this.reconnectTimer);
if (this.websocket) {
this.websocket.close();
this.websocket = null;
}
}
}
2. 代码解析
- 构造函数:接收
url
作为 WebSocket 连接地址,reconnectInterval
为重连间隔时间(默认 5000 毫秒),maxReconnectAttempts
为最大重连次数(默认 10 次)。同时初始化重连尝试次数reconnectAttempts
和重连定时器reconnectTimer
。 - connect 方法:检查 WebSocket 是否已经打开,若已打开则直接返回。否则使用
uni.connectSocket
建立连接,连接成功则重置重连尝试次数,失败则调用tryReconnect
方法尝试重连。 - setupEventListeners 方法:为 WebSocket 实例添加
onOpen
、onError
、onClose
和onMessage
事件监听器。在连接打开时重置重连尝试次数并清除定时器;在发生错误或连接关闭时调用tryReconnect
方法。 - tryReconnect 方法:检查重连尝试次数是否超过最大重连次数,若未超过则增加尝试次数,并使用
setTimeout
定时进行重连;若超过则输出错误信息停止重连。 - send 方法:检查 WebSocket 是否连接且处于打开状态,若满足条件则将数据转换为 JSON 字符串发送。
- on 方法:用于注册特定类型消息的回调函数。
- close 方法:清除重连定时器,关闭 WebSocket 连接并将实例置为
null
。
三、在页面中使用封装的 WebSocket
1. 引入并使用
在需要使用 WebSocket 的页面中,引入封装好的 WebSocketUtil
类,并进行连接、消息发送和关闭等操作。
<template>
<view class="container">
<button @click="connect">连接 WebSocket</button>
<button @click="sendMessage">发送消息</button>
<button @click="closeSocket">关闭 WebSocket</button>
</view>
</template>
<script>
import WebSocketUtil from '@/utils/websocket.js';
export default {
data() {
return {
webSocket: null
};
},
methods: {
async connect() {
const url = 'ws://your-server-url';
this.webSocket = new WebSocketUtil(url);
try {
await this.webSocket.connect();
this.webSocket.on('messageType', (data) => {
console.log('接收到消息', data);
});
} catch (error) {
console.error('连接失败', error);
}
},
sendMessage() {
const message = {
type:'messageType',
content: 'Hello, WebSocket!'
};
if (this.webSocket) {
this.webSocket.send(message);
}
},
closeSocket() {
if (this.webSocket) {
this.webSocket.close();
this.webSocket = null;
}
}
}
};
</script>
<style scoped>
.container {
padding: 20px;
}
</style>
2. 代码解析
- 引入 WebSocketUtil:通过
import WebSocketUtil from '@/utils/websocket.js';
引入封装类。 - 连接 WebSocket:在
connect
方法中创建WebSocketUtil
实例并调用connect
方法进行连接,连接成功后注册消息回调函数。 - 发送消息:在
sendMessage
方法中构造消息对象并调用send
方法发送。 - 关闭 WebSocket:在
closeSocket
方法中调用close
方法关闭连接并清空实例。
四、注意事项
1. 跨域问题
如果服务器和前端应用部署在不同的域下,需要在服务器端配置 CORS(跨域资源共享),允许前端应用的域名访问 WebSocket 服务。
2. 数据安全
在通过 WebSocket 传输数据时,对于敏感数据要进行加密处理,防止数据在传输过程中被窃取或篡改。
3. 重连策略调整
可以根据实际网络环境和业务需求调整重连间隔时间和最大重连次数,以平衡重连的及时性和资源消耗。
五、总结
通过以上步骤,我们成功在 UniApp 中封装了带有重连机制的 WebSocket。这种封装方式不仅使 WebSocket 的使用更加简洁和易于维护,还能有效应对网络不稳定导致的连接中断问题,提高了应用的稳定性和可靠性。在实际项目中,可以根据具体需求进一步优化重连策略和数据处理逻辑,以更好地满足实时通信的需求。希望本文能为你在 UniApp 项目中实现 WebSocket 通信提供有价值的参考。