从这篇文章接着向下看:
uniapp plus-websocket 和stompjs连接教程 安卓ios手机端有效 - 简书
按照文章的方式,能够实现APP下stmopjs长连接。但是有一个问题,就是会频繁输出
res-创建连接-1-
跟踪连接,会发现连接都会在大约40s后掉线断开,然后由于stompjs保活机制又进行重连。在重连过程中,对应的消息接收不到。导致出现部分消息丢失的情况。
目前解决的办法,是自己实现一个心跳逻辑,每隔指定的时间发送。就完成了连接保活。修改如下:
import socket from 'plus-websocket'class WebSocketPolyfill {constructor(url) {
。。。。connected() {return socket.connected}
}export default WebSocketPolyfill
client = new Client({// #ifndef H5webSocketFactory() {if (isMp) {// 微信小程序return new Ws({url: amqpServerUrl,protocols: ['v12.stomp', 'v11.stomp', 'v10.stomp'] // ← 这是 stomp 协议的默认写法,可供参考})} else {appWs = new WebSocket(amqpServerUrl)return appWs// Android | IOS}},。。。。。const appHeartbeat = () => {setTimeout(() => {if (appWs.connected) {const buffer = new ArrayBuffer(1) // 创建一个1字节的ArrayBufferconst view = new Uint8Array(buffer)view[0] = 0x09 // 根据RFC6455, opcode 0x9 表示ping帧appWs.send(buffer)appHeartbeat()}}, HEARTBEAT_INTERVAL)
}
然后在onConnect后激活心跳
onConnect: () => {// connect to user channel....// #ifdef APP-PLUSappHeartbeat()// #endif},
这样就解决了掉线问题
----------------------[2024/11/21新增]-----------------------
长链接睡死问题的解决
当屏幕休眠超过20分钟时,在IOS及安卓系统可能由于资源释放导致socket无法重连。上面这种方案无法直接断开链接重连。必须通过重载APP解决,因此实现一个变量和两个方法,在APP隐藏显示时进行计算,如果熄屏或挂起超过20分钟,则加载首页来实现长链接重载。
let hideTick: number = -1export const watchHide = () => {hideTick = new Date().getTime()}export const watchShow = async () => {// 如果休息时间太久,就回首页重置长连接,避免睡死if (hideTick > 0 &&new Date().getTime() - hideTick > FORCE_RECONNECT_ON_SLEEP_SEC &¤tUserId) {await leaveUserChannel() //deactivate长链接,close socketsetTimeout(() => {// 休息太久了,去首页utils.reLaunch('/pages/index/index')}, 1000)}hideTick = -1}
在APP.vue的show和hide分别执行watchShow和watchHide即可
下面是完整的plus-websocket封装单元(该单元已废弃,由于plus-websocket大并发时丢失消息的问题,已重写替代模块,请见我另一篇《plus-websocket替代websocket封装模块》:
websocket-app.js:
/*** 封装 plus-websocket 文件*/
import socket from 'plus-websocket'class WebSocketPolyfill {constructor(url) {// 创建连接socket.connectSocket({url,success: function (res) {console.log('res-创建连接-1-', res)}})// 连接开启socket.onSocketOpen((res) => {this.onopen(res)})// 连接关闭socket.onSocketClose((res) => {this.onclose(res)})// 连接异常socket.onSocketError((res) => {this.onerror(res)})// 接收消息socket.onSocketMessage((res) => {this.onmessage(res)})}/*** 连接开启*/onopen(res) {}/*** 连接关闭*/onclose(res) {}/*** 连接异常*/onerror(res) {}/*** 接收消息*/onmessage(res) {}/*** 发送消息*/send(data) {socket.sendSocketMessage({data})}/*** 关闭连接*/close() {socket.closeSocket()}connected() {return socket.connected}
}export default WebSocketPolyfill