大家好,我是你的好朋友思创斯。今天说一说uni-app中websocket的使用 断开重连、心跳机制,希望您对编程的造诣更进一步.
最近关于h5和app的开发中使用到了websocket,由于web/app有时候会出现网络不稳定或者服务端主动断开,这时候导致消息推送不了的情况,需要客户端进行重连。查阅资料后发现了一个心跳机制,也就是客户端间隔一段时间就向服务器发送一条消息,如果服务器收到消息就回复一条信息过来,如果一定时间内没有回复,则表示已经与服务器断开连接了,这个时候就需要进行重连。
被动断开则进行重连,主动断开,不重连。
说明:下图针对两个tab项(open trades 和 closed trades),只希望在 tabindex = 0 (open trades 高亮时)触发websocket , 如果点击第二个栏目 , tabindex = 1(closed trades高亮时)则主动关闭websodket连接。
tabindex = 0 时 ,被动断开则自动重连
原文链接:uni-app中websocket的使用 断开重连、心跳机制
1.webscoket连接并接收推送的消息
2.将接收的消息转换成目标数据,并渲染
3.如果主动关闭,则不进行重连,监听关闭事件
4.显示已关闭,不重连
5.监听错误事件,比如地址,协议错误等,则会自动重连五次,五次重连仍失败后则需要进行手动重连
6.如果服务端主动断开,心跳机制会每隔一段时间发送一条数据给服务端,如果没有回复则会进行webscoket重连。
- 新建 socket.js , 将以下代码复制进去 ,向外暴露。
import api from '@/common/js/config.js' // 接口api,图片地址等等配置,可根据自身情况引入,也可以直接在下面url填入你的 websocket连接地址class socketio { constructor(data, time, url) { this.sockettask = null this.is_open_socket = false //避免重复连接 this.url = url ? url : api.websocketurl //连接地址 this.data = data ? data : null this.connectnum = 1 // 重连次数 this.traderdetailindex = 100 // traderdetailindex ==2 重连 this.accountstateindex = 100 // traderdetailindex ==1 重连 this.followflake = false // traderdetailindex == true 重连 //心跳检测 this.timeout = time ? time : 15000 //多少秒执行检测 this.heartbeatinterval = null //检测服务器端是否还活着 this.reconnecttimeout = null //重连之后多久再次重连 } // 进入这个页面的时候创建websocket连接【整个页面随时使用】 connectsocketinit(data) { this.data = data this.sockettask = uni.connectsocket({ url: this.url, success: () => { console.log("正准备建立websocket中..."); // 返回实例 return this.sockettask }, }); this.sockettask.onopen((res) => { this.connectnum = 1 console.log("websocket连接正常!"); this.send(data) clearinterval(this.reconnecttimeout) clearinterval(this.heartbeatinterval) this.is_open_socket = true; this.start(); // 注:只有连接正常打开中 ,才能正常收到消息 this.sockettask.onmessage((e) => { // 字符串转json let res = json.parse(e.data); console.log("res---------->", res) // 这里 查看 推送过来的消息 if (res.data) { uni.$emit('getpositonsorder', res); } }); }) // 监听连接失败,这里代码我注释掉的原因是因为如果服务器关闭后,和下面的onclose方法一起发起重连操作,这样会导致重复连接 uni.onsocketerror((res) => { console.log('websocket连接打开失败,请检查!'); this.sockettask = null this.is_open_socket = false; clearinterval(this.heartbeatinterval) clearinterval(this.reconnecttimeout) uni.$off('getpositonsorder') if (this.connectnum < 6) { uni.showtoast({ title: `websocket连接失败,正尝试第${this.connectnum}次连接`, icon: "none" }) this.reconnect(); this.connectnum = 1 } else { uni.$emit('connecterror'); this.connectnum = 1 } }); // 这里仅是事件监听【如果socket关闭了会执行】 this.sockettask.onclose(() => { console.log("已经被关闭了-------") clearinterval(this.heartbeatinterval) clearinterval(this.reconnecttimeout) this.is_open_socket = false; this.sockettask = null uni.$off('getpositonsorder') if (this.connectnum < 6) { this.reconnect(); } else { uni.$emit('connecterror'); this.connectnum = 1 } }) } // 主动关闭socket连接 close() { if (!this.is_open_socket) { return } this.sockettask.close({ success() { uni.showtoast({ title: 'sockettask 关闭成功', icon: "none" }); } }); } //发送消息 send(data) { console.log("data---------->", data); // 注:只有连接正常打开中 ,才能正常成功发送消息 if (this.sockettask) { this.sockettask.send({ data: json.stringify(data), async success() { console.log("消息发送成功"); }, }); } } //开启心跳检测 start() { this.heartbeatinterval = setinterval(() => { this.send({ "traderid": 10260, "type": "ping" }); }, this.timeout) } //重新连接 reconnect() { //停止发送心跳 clearinterval(this.heartbeatinterval) //如果不是人为关闭的话,进行重连 if (!this.is_open_socket && (this.traderdetailindex == 2 || this.accountstateindex == 0 || this .followflake)) { this.reconnecttimeout = setinterval(() => { this.connectsocketinit(this.data); }, 5000) } } /** * @description 将 scoket 数据进行过滤 * @param {array} array * @param {string} type 区分 弹窗 openposition 分为跟随和我的 */ arrayfilter(array, type = 'normal', signalid = 0) { let arr1 = [] let arr2 = [] let obj = { arr1: [], arr2: [] } arr1 = array.filter(v => v.flwsig == true) arr2 = array.filter(v => v.flwsig == false) if (type == 'normal') { if (signalid) { arr1 = array.filter(v => v.flwsig == true && v.sigtraderid == signalid) return arr1 } else { return arr1.concat(arr2) } } else { if (signalid > 0) { arr1 = array.filter(v => v.flwsig == true && v.sigtraderid == signalid) obj.arr1 = arr1 } else { obj.arr1 = arr1 } obj.arr2 = arr2 return obj } }}module.exports = socketio
- 在入口文件中 将 socketio 挂载在 vue 原型上 , 也可以按需引入置顶页面 。
import socketio from '@/common/js/scoket.js'vue.prototype.socketio = new socketio()
- 在需要用到websocket的页面中使用如下方法(可根据自身业务需求进行整改)
scoketclose() { this.socketio.connectnum = 1 const data = { "value1": "demo1" "value2": "demo2" } this.socketio.send(data) // 这是给后端发送特定数据 关闭推送 this.socketio.close() // 主动 关闭连接 , 不会重连},getwebsocketdata() { // 要发送的数据包 const data = { "value": "value1", "type": "type1" } // 打开连接 this.socketio.connectsocketinit(data) // 接收数据 uni.$on("getpositonsorder", (res) => { this.connect = true const { code, data } = res if (code == xxxx) { // 根据后端传过来的数据进行 业务编写。。。 } else { } }) // 错误时做些什么 uni.$on("connecterror", () => { this.connect = false this.scoketerror = true })}
- 离开页面,记得断开连接。
onunload() { this.scoketclose() this.socketio.traderdetailindex = 100 // 初始化 tabindex }
如果在使用中遇到什么问题 ,可以给我 留言 ,看到留言后会在第一时间进行回复 。
文章由思创斯整理,转载请注明出处:https://ispacesoft.com/124501.html