前言

在当今互联网应用中,实时通信已经成为一个标配功能,特别是对于需要即时响应的场景,如在线客服、咨询系统等。本文将分享如何在小程序中实现一个高效稳定的WebSocket连接,以及如何处理断线重连、消息发送与接收等常见问题。

WebSocket简介

WebSocket是HTML5提供的一种在单个TCP连接上进行全双工通讯的协议。相比传统的HTTP请求,WebSocket具有以下优势:

  1. 持久连接:一次握手,持续通信,避免了HTTP的重复连接
  2. 低延迟:全双工通信,服务端可以主动推送数据
  3. 较小的数据包开销:相比HTTP请求的头信息,WebSocket的数据包头较小

在小程序中实现WebSocket连接

小程序提供了uni.connectSocket等API来支持WebSocket连接。以下是一个完整实现的代码示例:

initSocket() {try {if (!this.token) { return; }uni.connectSocket({ url: 'ws://example-domain.com:8000?token=' + this.token });uni.onSocketOpen(() => { console.log('WebSocket 已连接'); this.socketActive = true; this.reconnectCount = 0; });uni.onSocketMessage((res) => {// 处理接收到的消息try {// 尝试解析JSON格式的消息const msgData = JSON.parse(res.data);// 判断消息类型if (msgData.type === 'msg') {// 如果是消息类型,提取content内容并显示const messageText = msgData.content || '';if (messageText) {this.messages.push({from: 'other',text: messageText,time: this.formatTime(new Date())});this.$nextTick(() => { this.toBottom(); });}} else {// 其他类型的消息console.log('收到非消息类型的数据:', msgData);}} catch (e) {// 如果不是JSON格式,直接显示原始文本console.log('消息不是JSON格式,直接显示:', res.data);this.messages.push({from: 'other',text: res.data,time: this.formatTime(new Date())});this.$nextTick(() => { this.toBottom(); });}});uni.onSocketError((err) => { console.error('WebSocket 错误', err); this.socketActive = false; this.tryReconnect(); });uni.onSocketClose(() => { console.log('WebSocket 已关闭'); this.socketActive = false; this.tryReconnect(); });} catch (e) { console.error('WebSocket 创建失败', e); }
}

断线重连机制

一个稳定的WebSocket实现必须考虑断线重连机制。以下是一个简单而高效的重连实现:

tryReconnect() {if (!this.token) return;if (!this.isPageVisible) return;if (this.reconnectCount >= this.maxReconnect) return;if (this.reconnectTimer) return; // 已经计划了重连this.reconnectCount++;this.reconnectTimer = setTimeout(() => {this.reconnectTimer = null;console.log('尝试重连 WebSocket, 第' + this.reconnectCount + '次');this.initSocket();}, 3000); // 3秒后尝试重连
}closeSocket() {if (this.reconnectTimer) {clearTimeout(this.reconnectTimer);this.reconnectTimer = null;}if (this.socketActive) {console.log('主动断开WebSocket连接');uni.closeSocket();this.socketActive = false;}
}

处理页面生命周期

在小程序中,我们需要在适当的页面生命周期中管理WebSocket连接:

onLoad() {this.isPageVisible = true;this.token = wx.getStorageSync('token') || '';if (this.token) {this.initSocket();// 定期发送心跳包setTimeout(() => {this.ping();}, 30000);}// 其他初始化代码...
}onUnload() {this.closeSocket();this.isPageVisible = false;
}onHide() {// 页面隐藏时断开连接this.closeSocket();this.isPageVisible = false;
}onShow() {// 页面显示时重新连接this.isPageVisible = true;if (this.token && !this.socketActive) {this.initSocket();}
}

心跳机制

为了保持连接活跃并检测连接状态,实现心跳机制是必要的:

ping() {if (!this.token) {return;}if (!this.isPageVisible) {return;}// 发送心跳包if (this.socketActive) {uni.sendSocketMessage({ data: `{"type":"ping"}` });} else {this.messages.push({from: 'other',text: '连接已断开,正在重连...',time: this.formatTime(new Date())});this.tryReconnect();}
}

发送消息

当用户发送消息时,需要检查连接状态并正确格式化消息:

send() {const txt = this.newMsg.trim();if (!txt) return;if (!this.token) {uni.navigateTo({ url: '/pages/login/login' });return;}// 添加消息到本地列表this.messages.push({from: 'me',text: txt,time: this.formatTime(new Date())});this.newMsg = '';// 发送到服务器if (this.socketActive) {uni.sendSocketMessage({ data: `{"type":"msg","content":"${txt}"}` });} else {this.messages.push({from: 'other',text: '连接已断开,正在重连...',time: this.formatTime(new Date())});this.tryReconnect();}
}

加载历史消息

为了提供更好的用户体验,我们可以在建立WebSocket连接后加载历史消息:

async loadHistoryMessages() {try {const res = await this.$axios("api/historyMessages", { limit: 100 });if (res.data.code == 0) {// 处理历史消息数据const historyData = res.data.lists || [];// 处理逻辑...}} catch (e) {console.error("加载历史记录失败", e);}
}

优化用户体验的技巧

  1. 消息发送状态:可以为每条消息添加状态标记,如"发送中"、“已发送”、“发送失败”
  2. 消息队列:当连接断开时,可以将消息加入队列,连接恢复后再发送
  3. 渐进式加载:历史消息可以分页加载,以提高初始加载速度
  4. 消息格式化:支持不同类型的消息格式,如文本、图片、链接等
  5. 连接状态提示:在UI上显示当前连接状态,让用户了解实时情况

总结

在小程序中实现WebSocket可以大大提升实时通信体验。本文介绍了WebSocket的基本实现、断线重连、心跳机制等关键技术点。希望这些经验能帮助你在自己的项目中构建更稳定、高效的实时通信功能。

记住,一个健壮的WebSocket实现需要考虑各种边缘情况,包括网络波动、设备切换、应用切换等场景。通过合理的重连策略和状态管理,我们可以为用户提供流畅的实时通信体验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/87600.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/87600.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/87600.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python网络爬虫编程新手篇

网络爬虫是一种自动抓取互联网信息的脚本程序,广泛应用于搜索引擎、数据分析和内容聚合。这次我将带大家使用Python快速构建一个基础爬虫,为什么使用python做爬虫?主要就是支持的库很多,而且同类型查询文档多,在同等情…

LeetCode.283移动零

题目链接:283. 移动零 - 力扣(LeetCode) 题目描述: 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行…

2025年7月4日漏洞文字版表述一句话版本(漏洞危害以及修复建议),通常用于漏洞通报中简洁干练【持续更新中】,漏洞通报中对于各类漏洞及修复指南

漏洞及修复指南 一、暗链 危害:攻击者通过技术手段在用户网页中插入隐藏链接或代码,并指向恶意网站,可导致用户信息泄露、系统感染病毒,用户访问被劫持至恶意网站,泄露隐私或感染恶意软件,被黑客利用进行…

python --飞浆离线ocr使用/paddleocr

依赖 # python3.7.3 paddleocr2.7.0.2 paddlepaddle2.5.2 loguru0.7.3from paddleocr import PaddleOCR import cv2 import numpy as npif __name__ __main__:OCR PaddleOCR(use_doc_orientation_classifyFalse, # 检测文档方向use_doc_unwarpingFalse, # 矫正扭曲文档use…

数据结构与算法:贪心(三)

前言 感觉开始打cf了以后贪心的能力有了明显的提升,让我们谢谢cf的感觉场。 一、跳跃游戏 II class Solution { public:int jump(vector<int>& nums) {int n=nums.size();//怎么感觉这个题也在洛谷上刷过(?)int cur=0;//当前步最远位置int next=0;//多跳一步最远…

【Redis篇】数据库架构演进中Redis缓存的技术必然性—高并发场景下穿透、击穿、雪崩的体系化解决方案

&#x1f4ab;《博主主页》&#xff1a;    &#x1f50e; CSDN主页__奈斯DB    &#x1f50e; IF Club社区主页__奈斯、 &#x1f525;《擅长领域》&#xff1a;擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控&#xff1b;并对…

Docker 实践与应用案例

引言 在当今的软件开发和部署领域&#xff0c;高效、可移植且一致的环境搭建与应用部署是至关重要的。Docker 作为一款轻量级的容器化技术&#xff0c;为解决这些问题提供了卓越的方案。Docker 通过容器化的方式&#xff0c;将应用及其依赖项打包成一个独立的容器&#xff0c;…

《论三生原理》以非共识路径实现技术代际跃迁‌?

AI辅助创作&#xff1a; 《论三生原理》以颠覆传统数学范式的非共识路径驱动多重技术代际跃迁&#xff0c;其突破性实践与争议并存&#xff0c;核心论证如下&#xff1a; 一、技术代际跃迁的实证突破‌ ‌芯片架构革新‌ 为华为三进制逻辑门芯片提供理论支撑&#xff0c;通过对…

一体机电脑为何热度持续上升?消费者更看重哪些功能?

一体机电脑&#xff08;AIO&#xff0c;All-in-One&#xff09;将主机硬件与显示器集成于单一机身。通常仅需连接电源线&#xff0c;配备无线键盘、鼠标即可启用。相比传统台式电脑和笔记本电脑&#xff0c;选购一体机的客户更看重一体机的以下特点。 一体机凭借其节省空间、简…

无人机载重模块技术要点分析

一、技术要点 1. 结构设计创新 双电机卷扬系统&#xff1a;采用主电机&#xff08;张力控制&#xff09;和副电机&#xff08;卷扬控制&#xff09;协同工作&#xff0c;解决绳索缠绕问题&#xff0c;支持30米绳长1.2m/s高速收放&#xff0c;重载稳定性提升。 轴双桨布局…

【大模型推理】工作负载的弹性伸缩

基于Knative的LLM推理场景弹性伸缩方案 1.QPS 不是一个好的 pod autoscaling indicator 在LLM推理中&#xff0c; 为什么 2. concurrency适用于单次请求资源消耗大且处理时间长的业务&#xff0c;而rps则适合较短处理时间的业务。 3.“反向弹性伸缩”的概念 4。 区分两种不同的…

STM32F103_Bootloader程序开发12 - IAP升级全流程

导言 本教程使用正点原子战舰板开发。 《STM32F103_Bootloader程序开发11 - 实现 App 安全跳转至 Bootloader》上一章节实现App跳转bootloader&#xff0c;接着&#xff0c;跳转到bootloader后&#xff0c;下位机要发送报文‘C’给IAP上位机&#xff0c;表示我准备好接收固件数…

AI驱动的未来软件工程范式

引言&#xff1a;迈向智能驱动的软件工程新范式 本文是一份关于构建和实施“AI驱动的全生命周期软件工程范式”的简要集成指南。它旨在提供一个独立、完整、具体的框架&#xff0c;指导组织如何将AI智能体深度融合到软件开发的每一个环节&#xff0c;实现从概念到运维的智能化…

Hawk Insight|美国6月非农数据点评:情况远没有看上去那么好

7月3日&#xff0c;美国近期最重要的劳动力数据——6月非农数据公布。在ADP遇冷之后&#xff0c;市场对这份报告格外期待。 根据美国劳工统计局公布报告&#xff0c;美国6月非农就业人口增加 14.7万人&#xff0c;预期 10.6万人&#xff0c;4月和5月非农就业人数合计上修1.6万人…

Python 的内置函数 reversed

Python 内建函数列表 > Python 的内置函数 reversed Python 的内置函数 reversed() 是一个用于序列反转的高效工具函数&#xff0c;它返回一个反向迭代器对象。以下是关于该函数的详细说明&#xff1a; 基本用法 语法&#xff1a;reversed(seq)参数&#xff1a;seq 可以是…

沟通-交流-说话-gt-jl-sh-goutong-jiaoliu-shuohua

沟通,先看|问状态(情绪) 老婆下班回家,我说,到哪儿了,买点玉米哦;她说你为啥不买, 我说怎么如此大火气, 她说你安排我&#xff0c;我不情愿;你怎么看 和女人沟通不能目标优先 先问状态并表达关心 用感谢代替要求&#xff08;“你上次买的玉米特别甜&#xff0c;今天突然又馋了…

Ubuntu20.04运DS-5

准备工作&#xff1a; cd /home/rlk/rlk/runninglinuxkernel_5.0 #make clean mkdir _install_arm64/dev sudo mknod _install_arm64/dev/console c 5 1 ./build_ds5_arm64.sh git checkout boot-wrapper-aarch64/fvp-base-gicv3-psci.dtb ./build_ds5_arm64.sh创建工程步骤2.5…

区块链网络P2P通信原理

目录 区块链网络P2P通信原理引言:去中心化的网络基石1. P2P网络基础架构1.1 区块链网络拓扑1.2 节点类型对比2. 节点发现与连接2.1 初始引导过程2.2 节点发现协议3. 网络通信协议3.1 消息结构3.2 核心消息类型4. 数据传播机制4.1 交易传播流程4.2 Gossip协议实现4.3 区块传播优…

RNN和Transformer区别

RNN&#xff08;循环神经网络&#xff09;和 Transformer 是两种广泛应用于自然语言处理&#xff08;NLP&#xff09;和其他序列任务的深度学习架构。它们在设计理念、性能特点和应用场景上存在显著区别。以下是它们的详细对比&#xff1a;1. 基本架构RNN&#xff08;循环神经网…

[学习记录]Unity-Shader-几何着色器

几何着色器是可编程渲染管线中的一个可选阶段&#xff0c;位于顶点着色器之后和片段着色器之前。其核心能力在于动态生成和操作几何体图元。 一.图元 了解图元是理解几何着色器的基础和前提&#xff0c;因为几何着色器的工作就是接收图元&#xff0c;然后输出图元。 几何着色…