基于uniapp使用websocket进行实时通讯

发布于:2024-12-18 ⋅ 阅读:(9) ⋅ 点赞:(0)

前言

最近在做一个赛事的需求,需要使用实时通讯实现房间内交换位置,转让房主,踢出房间等操作

记录一下基于uniapp中websocket的封装和使用

话不投机半句多(少bb),准备动手,准备动手

Snipaste_2024-11-19_15-12-42.png

ws方法封装

1. 类定义
  • 类名WebsocketTask

  • 私有属性:

    • #heartbeatInterval: 心跳定时器。
    • #callback: 回调函数。
    • #websocketStatus: WebSocket 连接状态。
    • #isClosed: 是否主动关闭。
	/** 心跳定时器 */
	#heartbeatInterval = null
	/** 回调函数 */
	#callback = null
	/** ws状态 */
	#websocketStatus = false
	/** 是否主动关闭 */
	#isClosed = false
2. 构造函数
  • 参数:

    • url: WebSocket 服务器地址。
    • interval: 心跳间隔时间。
  • 功能:

    • 初始化 url 和 intervalTime
    • 注释掉的代码块用于在实例化时立即连接 WebSocket,并在连接失败时尝试重连。
	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' }
	/** 开始心跳 */
	#startHeartbeat() {
		this.#heartbeatInterval = setInterval(() => {
			this.sendMessage({
				cmd: 'ping'
			})
		}, this.intervalTime)
	}
3.3 sendMessage
  • 参数:

    • data: 要发送的消息内容。
  • 功能: 发送消息。

  • 步骤:

    • 生成消息序列号 seq
    • 如果消息不是心跳或退出命令且 WebSocket 未就绪,则稍后重试。
    • 发送消息并记录日志。
	/**
	 * 发送消息
	 * @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: 回调函数。
  • 功能: 设置消息接收的回调函数。

	/** 设置回调 */
	setCallback(cb) {
		this.#callback = cb
	}
	
3.5 reconnect
  • 功能: 重新连接 WebSocket。

  • 步骤:

    • 清除心跳定时器。
    • 如果 WebSocket 未就绪,则延迟 3 秒后重新初始化连接。
	reconnect() {
		clearInterval(this.#heartbeatInterval)
		if(!this.#websocketStatus) {
			setTimeout(() => {
				this.initWebsocket()
			}, 3000);
		}
	}
3.6 disconnect
  • 功能: 主动断开 WebSocket 连接。

  • 步骤:

    • 使用 uni.closeSocket 关闭连接。
    • 设置状态为未连接和已关闭。
    • 清除心跳定时器。
	/** 主动断开连接 */
	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 连接。
//main.js
Vue.prototype.$websocket = new WebsocketTask('ws://test.com', 3000)
const app = new Vue({
  i18n,
  ...App
})
app.$mount()

页面中的使用

  • 初始化ws:
//demo.vue
onLoad(){
   this.$websocket.initWebsocket()
   //设置回调
}
  • 设置回调:
//demo.vue
onLoad(){
   this.$websocket.setCallback((msg)=>{
       //收到消息时的回调函数
       this.decodeWsMsg(msg)
   })
   //设置回调
}
methods: {
   //处理ws消息
   decodeWsMsg(msg) {
   }
}
  • 发送信息:
 //demo.vue
methods: {
    sendMsg(msg) {
        this.$websocket.sendMessage({value: 'hello, 我是郭德纲'})
    }
}
  • 断开ws:
 //demo.vue
 onUnload() {
    // 主动断开连接
    this.$websocket.disconnect()
 },

总结

  • WebsocketTask 类封装了 WebSocket 的连接、消息发送、心跳机制和重连逻辑。
  • 提供了回调函数设置和主动断开连接的方法。
  • 使用 uni.connectSocket 进行 WebSocket 连接,适用于 Uni-app。
  • WebSocket实例挂载到vue全局
  • 在具体页面中使用this.$websocket 访问到这个 WebSocket 实例,调用实例的方法进行连接、消息发送、处理消息、断开连接、重连等操作。

参考文档:

uniapp-websocket

uniapp-SocketTask


至此,WebSocket的封装和简单使用已经介绍完了 ★,°:.☆( ̄▽ ̄)/$:*.°★

下次再见!(●’◡’●)

Snipaste_2024-11-08_15-32-07.png