前言
最近在做一个赛事的需求,需要使用实时通讯实现房间内交换位置,转让房主,踢出房间等操作
记录一下基于uniapp中websocket的封装和使用
话不投机半句多(少bb),准备动手,准备动手
ws方法封装
1. 类定义
-
类名 :
WebsocketTask
-
私有属性:
#heartbeatInterval
: 心跳定时器。#callback
: 回调函数。#websocketStatus
: WebSocket 连接状态。#isClosed
: 是否主动关闭。
js
/** 心跳定时器 */
#heartbeatInterval = null
/** 回调函数 */
#callback = null
/** ws状态 */
#websocketStatus = false
/** 是否主动关闭 */
#isClosed = false
2. 构造函数
-
参数:
url
: WebSocket 服务器地址。interval
: 心跳间隔时间。
-
功能:
- 初始化
url
和intervalTime
。 - 注释掉的代码块用于在实例化时立即连接 WebSocket,并在连接失败时尝试重连。
- 初始化
js
constructor (url, interval) {
this.url = url
this.intervalTime = interval
// 实例化时立即连接ws。根据需求启用
// try {
// return this.initWebsocket()
// } catch (e) {
// this.#websocketStatus = false
// this.reconnect()
// }
}
3. 方法
3.1 initWebsocket
-
功能: 初始化 WebSocket 连接。
-
步骤:
- 使用
uni.connectSocket
创建 WebSocket 连接。 - 监听
onOpen
事件,连接成功后启动心跳定时器并设置状态。 - 监听
onMessage
事件,处理接收到的消息。 - 监听
onError
事件,处理连接错误。 - 监听
onClose
事件,处理连接关闭,并在非主动关闭时尝试重连。
- 使用
3.2 #startHeartbeat
-
功能: 启动心跳定时器。
-
步骤:
- 使用
setInterval
定期发送心跳消息{ cmd: 'ping' }
。
- 使用
js
/** 开始心跳 */
#startHeartbeat() {
this.#heartbeatInterval = setInterval(() => {
this.sendMessage({
cmd: 'ping'
})
}, this.intervalTime)
}
3.3 sendMessage
-
参数:
data
: 要发送的消息内容。
-
功能: 发送消息。
-
步骤:
- 生成消息序列号
seq
。 - 如果消息不是心跳或退出命令且 WebSocket 未就绪,则稍后重试。
- 发送消息并记录日志。
- 生成消息序列号
js
/**
* 发送消息
* @param {*} data 消息内容
*/
sendMessage (data) {
let seq = Date.now().toString()
if (data.cmd !== 'ping' && data.cmd !== 'exit') {
// 未就绪时稍后重试
if (!this.#websocketStatus) {
console.warn(' [Websocket] 未就绪', JSON.stringify(data))
return setTimeout(() => {
this.sendMessage({...data, seq})
}, this.intervalTime);
}
console.log('%c [Websocket] ', 'background: #2888D9;', '发送消息:', JSON.stringify(data))
}
this.socketTask.send({
data: JSON.stringify(data)
})
}
3.4 setCallback
-
参数:
cb
: 回调函数。
-
功能: 设置消息接收的回调函数。
js
/** 设置回调 */
setCallback(cb) {
this.#callback = cb
}
3.5 reconnect
-
功能: 重新连接 WebSocket。
-
步骤:
- 清除心跳定时器。
- 如果 WebSocket 未就绪,则延迟 3 秒后重新初始化连接。
js
reconnect() {
clearInterval(this.#heartbeatInterval)
if(!this.#websocketStatus) {
setTimeout(() => {
this.initWebsocket()
}, 3000);
}
}
3.6 disconnect
-
功能: 主动断开 WebSocket 连接。
-
步骤:
- 使用
uni.closeSocket
关闭连接。 - 设置状态为未连接和已关闭。
- 清除心跳定时器。
- 使用
js
/** 主动断开连接 */
disconnect() {
uni.closeSocket()
this.#websocketStatus = false
this.#isClosed = true
clearInterval(this.#heartbeatInterval)
}
}
至此,WebsocketTask的类已经封装好了,里面包括了websocket连接、消息发送、心跳机制和重连。接着就是websocket的使用了。
把ws实例挂载到全局:
- 创建
WebsocketTask
实例: 实例化WebsocketTask
类,创建一个具体的 WebSocket 连接对象。 - 挂载到
Vue
原型: 为了避免在切换页面的时候导致ws连接断开,可以将ws实例化挂载至vue全局,使得在整个应用中可以通过this.$websocket
访问到这个 WebSocket 实例,方便管理和使用 WebSocket 连接。
js
//main.js
Vue.prototype.$websocket = new WebsocketTask('ws://test.com', 3000)
const app = new Vue({
i18n,
...App
})
app.$mount()
页面中的使用
- 初始化ws:
js
//demo.vue
onLoad(){
this.$websocket.initWebsocket()
//设置回调
}
- 设置回调:
js
//demo.vue
onLoad(){
this.$websocket.setCallback((msg)=>{
//收到消息时的回调函数
this.decodeWsMsg(msg)
})
//设置回调
}
methods: {
//处理ws消息
decodeWsMsg(msg) {
}
}
- 发送信息:
js
//demo.vue
methods: {
sendMsg(msg) {
this.$websocket.sendMessage({value: 'hello, 我是郭德纲'})
}
}
- 断开ws:
js
//demo.vue
onUnload() {
// 主动断开连接
this.$websocket.disconnect()
},
总结
WebsocketTask
类封装了 WebSocket 的连接、消息发送、心跳机制和重连逻辑。- 提供了回调函数设置和主动断开连接的方法。
- 使用
uni.connectSocket
进行 WebSocket 连接,适用于 Uni-app。 - 把
WebSocket
实例挂载到vue
全局 - 在具体页面中使用
this.$websocket
访问到这个 WebSocket 实例,调用实例的方法进行连接、消息发送、处理消息、断开连接、重连等操作。
参考文档:
至此,WebSocket的封装和简单使用已经介绍完了 ★,°:.☆( ̄▽ ̄)/$:*.°★
下次再见!(●'◡'●)