uniapp websocket 封装断线重连

 1.新建一个工具类js文件

2. 把我封装的代码复制进去

//引入vuex,因为我需要使用vuex存储得到的数据
import store from "@/store/index.js"
// 连接
let socketTask = null
// 是否主动关闭连接
let meClose = false
// 地址 写你的后端连接地址
let url = "ws://192.168.1.2:8888/ws/"
let token = null
// 重连定时器
let Time = null
// 心跳定时器
let XTime = null
// 开启连接
const sokcet = () => {
    // 我这个项目需要在连接的时候带token,不需要可以只写url地址
	token = uni.getStorageSync("token") //token
	// console.log(url + token);
	//判断是否有websocet对象,有的话清空
	if (socketTask) {
		uni.closeSocket()
		socketTask = null;
	}
	// 进行连接
	socketTask = uni.connectSocket({
		url: url + token, //仅为示例,并非真实接口地址。不需要带token可以只写url地址
		success(data) {
			clearInterval(Time) //关闭定时器
			clearInterval(XTime) //关闭心跳定时器
			console.log("创建连接!");
			// 监听是否连接
			uni.onSocketOpen((res) => {
				console.log('连接成功!获取离线信息');
				sendMsg("1000")
				clearInterval(Time) //关闭定时器
				clearInterval(XTime) //关闭心跳定时器
				// 5秒发送一次心跳//后端检测是否在线
				XTime = setInterval(() => {
					// console.log("心跳");
					sendMsg("2000")
				}, 5000)
			});
		}
	});

	// 监听连接失败
	uni.onSocketError((err) => {
		console.log('连接失败,请检查');
		if (!meClose) {//判断是否主动关闭进行重新连接
			reconnect()
		}
	})
	// 监听连接关闭close
	uni.onSocketClose((e) => {
		console.log('连接关闭!', meClose);
		if (!meClose) {//判断是否主动关闭进行重新连接
			reconnect()
		}
	})
	// 监听收到信息
	uni.onSocketMessage((res) => {
		let data = JSON.parse(res.data)
		// 接收数据后回调
		console.log('服务器内容:', data);
        // 我存储数据到vuex
		// 全部消息列表
		// store.commit("login/pushList", data)
		// 提醒消息列表 
		// store.commit("login/unshiftMessage", data)
		// 存储到本地
		// store.commit("login/setvuex")
		// uni.onPushMessage((res) => {
		// 	// 后台提醒内容 需要后端配置,也可以不要
		//if (uni.getStorageSync("uuid") != data.senderId) {
			//let name = data.names ? data.names : "新消息"
			//let text = data.payload.text ? data.payload.text : "你有一条新消息待查看"
			// console.log(name);
			// console.log(text);
			//uni.createPushMessage({
			//	title: name,
			//	content: text,
			//	sound: "system",
			//	icon: "/static/images/logobc.png",
			//	 payload:{
			//	这里地方你可以随意组合你想要的数据,uni.onPushMessage会监听到你组合的数据。
			//	 },
		//		success: (res => {
		//			 console.log('成功创建')
		//		}),
		//	})
		//}
		// console.log("收到推送消息:", JSON.parse(res.data)) //监听推送消息
		// })

	});
}
// 重新连接
const reconnect = () => {
	console.log("开始断线重连!!!!!!!!!!!");
	// 确保已经关闭后再重新打开
	uni.closeSocket()
	socketTask = '';
	console.log("重新连接中...");
	// console.log(url + token);
	sokcet(url + token)
}
//向后端发送信息
const sendMsg = (msg) => {
	msg = JSON.stringify(msg)
	// console.log(msg);
	//通过 WebSocket 连接发送数据
	uni.sendSocketMessage({
		data: msg,
		success() {
			// console.log("成功");
		},
		fail() {
			console.log("失败");
			uni.showLoading({
				title: "加载中..."
			})
			setTimeout(() => {
				uni.hideLoading()
			}, 1000)
			if (!meClose) {
				reconnect()
			}
		},
	});
}
// 手动关闭连接
const stop = () => {
	// 主动关闭连接
	meClose = true
	uni.closeSocket({
		success() {
			console.log("手动关闭成功!");
			clearInterval(Time) //关闭定时器
			clearInterval(XTime) //关闭心跳定时器
			// 确保已经关闭
			socketTask = null;
		}
	})
}
// 导出方法
export const websocetObj = {
	sokcet, //连接
	stop, //关闭
	sendMsg //发送
};

我是用uniapp 的api封装的 在外面也可以直接用uniapp的api操作

只有在开始调用连接需要用封装的方法调用

在需要使用封装的方法的页面 引入js

    import {
        websocetObj
    } from "@/API/websocket.js"

 完善重连

在app.vue的onShow生命周期发送心跳检测是否连接(写在这个生命周期可以提高连接速度)

// 发送一次心跳,没有成功就触发重新连接
  websocetObj.sendMsg("2000")

调用连接方法

//请求连接
 websocetObj.sokcet()

关闭连接

 // 关闭连接
  websocetObj.stop()

 发送消息

sendTextMessage() { //发送消息
                if (this.content.trim() != '') {
                    let date = new Date()
                    let jsondata = {
                        groups: 0,
                        payload: {
                            text: this.content,
                            tpUrl: "",
                            spUrl: ""
                        },
                        receiverId: this.frienduuid,
                        senderId: this.user.uuid,
                        names: this.user.names,
                        avatar: this.user.avatar,
                        status: "success",
                        timestamp: date.getTime(),
                        type: "text"
                    };

                     // 使用封装方法发送
                    // websocetObj.sendMsg(jsondata)

                    // 使用uniapp 原生方法发送(我使用原生方法是因为想加一个消息发送失败提醒)
                    let msg = JSON.stringify(jsondata);
                    uni.sendSocketMessage({
                        data: msg,
                        success: () => {
                            //发送成功的方法
                            console.log("给" + this.title + "消息发送成功");
                        },
                        fail() {
                            uni.showToast({
                                title: '消息发送失败,请检查网络',
                                icon: 'none'
                            });
                        }
                    });
                    // 调用滚动到最下面的方法
                    this.scrollToBottom();
                    // 清空输入框
                    this.content = "";
                }
            },

 这个就是断线重连的过程 自动检测到服务器断线然后自动重新连接,中间报错是正常的没有连接到的报错,直到连接成功获取离线消息表示连接好了

 封装思想:

通过uniapp提供的API方法进行封装

断线重连机制:

通过发送心跳检测是否能够发送成功判断是否连接

 有不理解的地方欢迎私信或者评论问!!

<think>好的,我现在要帮用户介绍如何在UniApp封装WebSocket。首先,我需要回忆一下UniApp的基本知识,它是一个使用Vue.js开发跨平台应用的框架,支持多个平台,比如小程序、H5App等。WebSocket在实时通信中很常用,比如聊天应用或者实时数据更新。用户可能需要一个可复用的封装库,以便在不同的项目中方便地使用WebSocket。 接下来,我需要考虑WebSocket的基本用法。在原生JavaScript中,WebSocket对象有onopen、onmessage、onerror、onclose等事件。在UniApp中,可能也是类似的,但需要注意不同平台的兼容性问题。比如,有些小程序平台可能有自己的WebSocket API,UniApp可能已经做了处理,统一了接口,所以封装的时候应该用UniApp提供的API,比如uni.connectSocket。 然后,用户可能希望封装后的WebSocket具备哪些功能呢?首先,可能需要自动连机制,这样在网络不稳定时能保持连接。然后,可能需要心跳机制,防止长时间无通信导致连接被断开。此外,可能需要管理订阅的消息类型,不同的消息对应不同的处理函数,这样业务逻辑更清晰。另外,错误处理和状态管理也很要,比如记录连接状态,方便UI显示。 接下来,我需要设计一个类,比如叫SocketClient,包含连接、关闭、发送消息等方法。构造函数可能需要传入配置参数,比如URL、连次数、心跳间隔等。这个类应该维护WebSocket实例,并且处理各种事件。 在连接方法中,使用uni.connectSocket创建连接,然后监听onOpen、onMessage、onError、onClose事件。当连接成功时,可能需要启动心跳检测,定时发送心跳消息。如果收到消息,应该根据消息类型分发给对应的处理函数。发送消息时,可能需要检查连接状态,如果未连接,则尝试连或者报错。 自动连的逻辑应该在onClose事件中处理,当连接非正常关闭时,进行试,直到达到最大连次数。同时,连可能需要指数退避策略,避免频繁请求。 心跳机制可以通过定时器实现,每隔一段时间发送心跳包,如果一定时间内没有收到响应,则认为连接断开,触发连。这需要发送心跳消息,并等待服务器的响应,可能需要在收到消息时置心跳检测的计时器。 对于消息订阅,可以使用一个对象来保存不同消息类型的回调函数,当收到消息时,解析消息类型,并调用对应的回调。例如,消息可能是JSON格式,包含type和data字段,根据type找到对应的处理函数。 错误处理方面,需要捕获并抛出错误事件,或者提供钩子函数让用户处理。同时,可以设置最大连次数,超过后触发错误回调。 状态管理方面,可以维护一个状态变量,比如connecting、connected、closed等,方便外部获取当前连接状态。 还需要考虑关闭连接的方法,手动关闭时,要清除心跳定时器,停止连逻辑,并调用uni.closeSocket。 最后,提供一个使用示例,展示如何实例化SocketClient,订阅消息,发送消息,处理错误等。可能还需要提示用户注意的事项,比如不同平台的差异,或者需要后端配合实现心跳等。 现在,我需要验证这些思路是否正确。比如,在UniApp中使用uni.connectSocket是否正确,是否有不同的参数配置。心跳机制是否需要前后端配合,比如服务器也需要回复心跳消息。自动连的次数和间隔是否合理,可能需要用户根据需求调整。消息格式是否应该由用户自定义,比如使用JSON还是其他格式,可能需要让封装库更灵活,允许用户自定义解析方式。 可能还需要处理WebSocket实例的创建和销毁,防止内存泄漏。在组件卸载或页面关闭时,正确关闭连接。另外,发送消息前需要确保连接已建立,否则可能需要将消息加入队列,在连接成功后发送,但这会增加复杂性,是否要实现这个功能取决于用户需求。 综上所述,封装的关键点包括:使用UniApp API创建和管理WebSocket连接,自动连,心跳机制,消息订阅与分发,错误处理和状态管理。需要将这些功能整合到一个类中,提供简洁的API供用户调用。</think>在 UniApp封装 WebSocket 可以提升代码复用性和可维护性,尤其适用于实时通信场景(如聊天、实时数据监控)。以下是基于 UniAppWebSocket 封装思路及示例: --- ### **核心功能设计** 1. **自动连** - 网络异常断开后自动尝试连。 2. **心跳机制** - 防止长时间无通信被服务器断开。 3. **消息管理** - 根据消息类型分发处理。 4. **状态管理** - 跟踪连接状态(连接中/已连接/断开)。 5. **错误处理** - 统一捕获异常并回调。 --- ### **封装代码示例** ```javascript class SocketClient { constructor(options) { this.options = { url: '', reconnectLimit: 5, // 最大连次数 reconnectInterval: 3000, // 连间隔 heartInterval: 15000, // 心跳间隔 ...options }; this.socket = null; this.reconnectCount = 0; this.listeners = {}; // 消息监听器 { type: callback } this.status = 'disconnected'; // 状态:connecting/connected/disconnected this.heartTimer = null; // 心跳定时器 } // 连接 WebSocket connect() { if (this.status === 'connecting') return; this.status = 'connecting'; this.socket = uni.connectSocket({ url: this.options.url, success: () => { this._initSocketEvent(); }, fail: (err) => { this._handleError(err); this.reconnect(); } }); } // 初始化事件监听 _initSocketEvent() { this.socket.onOpen(() => { this.status = 'connected'; this.reconnectCount = 0; // 连计数器 this._startHeartbeat(); console.log('WebSocket 连接成功'); }); this.socket.onMessage((res) => { try { const msg = JSON.parse(res.data); if (msg.type === 'pong') return; // 心跳响应 const handler = this.listeners[msg.type]; handler?.(msg.data); } catch (e) { this._handleError(e); } }); this.socket.onClose(() => { this.status = 'disconnected'; this._stopHeartbeat(); this.reconnect(); // 尝试自动连 }); this.socket.onError((err) => { this._handleError(err); this.reconnect(); }); } // 发送消息 send(type, data) { if (this.status !== 'connected') { console.error('WebSocket 未连接'); return; } this.socket.send({ data: JSON.stringify({ type, data }), success: () => {}, fail: (err) => this._handleError(err) }); } // 订阅消息 on(type, callback) { this.listeners[type] = callback; } // 关闭连接 close() { this.socket?.close(); this.status = 'disconnected'; this._stopHeartbeat(); this.reconnectCount = this.options.reconnectLimit; // 停止连 } // 自动连 reconnect() { if (this.reconnectCount >= this.options.reconnectLimit) return; setTimeout(() => { this.reconnectCount++; this.connect(); }, this.options.reconnectInterval); } // 心跳检测 _startHeartbeat() { this.heartTimer = setInterval(() => { this.send('ping', Date.now()); // 发送心跳包 }, this.options.heartInterval); } _stopHeartbeat() { clearInterval(this.heartTimer); } // 错误处理 _handleError(error) { console.error('WebSocket 错误:', error); this.options.onError?.(error); } } ``` --- ### **使用示例** ```javascript // 初始化实例 const ws = new SocketClient({ url: 'wss://your-websocket-url', onError: (err) => console.error('全局错误:', err) }); // 连接 ws.connect(); // 订阅消息 ws.on('chatMessage', (data) => { console.log('收到聊天消息:', data); }); // 发送消息 ws.send('chatMessage', { text: 'Hello!' }); // 手动关闭 // ws.close(); ``` --- ### **注意事项** 1. **跨平台兼容性**:UniApp 已统一各平台 WebSocket API,但部分小程序可能限制并发连接数。 2. **心跳协议**:需与后端约定心跳消息类型(如 `ping/pong`)。 3. **连策略**:可根据需求调整连次数和间隔(如指数退避)。 4. **消息格式**:示例使用 JSON,可按需修改为其他格式(如 Protobuf)。 通过此封装,可快速在 UniApp 项目中实现稳定可靠的 WebSocket 通信。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

巨蟹座守护骑士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值