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

前言

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

记录一下基于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 实例,调用实例的方法进行连接、消息发送、处理消息、断开连接、重连等操作。

参考文档:

uniapp-websocket

uniapp-SocketTask


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

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

相关推荐
-Marks-17 分钟前
【C++编程】STL容器(二)--- vector底层模拟实现(常用接口实现 | 扩容机制 | 深浅拷贝 | 迭代器失效)
开发语言·c++·vector·内存管理·迭代器失效·vector底层模拟实现
飘尘31 分钟前
SVG和Canvas,前端里的两支“画笔”,用的时候怎么选择?
前端·javascript·面试
Shadow(⊙o⊙)35 分钟前
C++11并发支持库
开发语言·c++
一技安身36 分钟前
【java】JDK8 + JDK17 绿色解压共存方案-全程不修改任何系统环境变量
java·开发语言
hudd6681 小时前
JavaEE 初阶 - 多线程(初阶)
java·开发语言·java-ee
I Am a robert girl2 小时前
稀有事件估计的迭代去对齐:从源码视角拆解重要性采样新范式
开发语言·python·机器学习·重要性采样·蒙特卡洛方法·稀有事件估计
计算机魔术师2 小时前
DeepSeek 据报道接近完成至少 800 亿元融资,腾讯与宁德时代参与
前端
golang学习记2 小时前
rust开发,选VS Code还是RustRover?
开发语言·后端·rust
可乐ea2 小时前
多模型编排的三层:框架、模型路由与提供商路由
前端·网络·人工智能·ai智能体·多智能体协作·多模型编排·大模型路由
打工仔折腾 AI2 小时前
从零写一个CAD 05:以鼠标为中心的滚轮缩放,招法能复用但顺序不能反
开发语言·后端·python·性能优化·计算机外设·swift·ai agent 实战