背景
近期在开发打牌记账微信小程序时,我们将房间这个业务场景做成了类似聊天室功能。
对房间内发生的动作,都能实时对其他人可见。 如:转账,离开,加入,结算等动作
其他人员都能实时接收到推送消息, 这个时候就需要websocket发挥作用。
但uniapp集成websocket 会出现断线的情况。
导致用户体验差,基经过一番排查,解决了异常。 感兴趣扫描下方小程序码在线体验.
解决方法
请先阅读之前文章uniapp集成websocket的前后端代码了解集成步骤。
一般情况下,小程序是由多个页面构成的,那么这里就有两种情况:
你的长连接返回的数据只是某一个页面需要用到,其他页面都没有用到;
你的长连接返回的数据不止一个页面用到,而是多个页面,这种情况当然也可以包括第一种情况。
- 单页面监听代码实现
var socket = null;
export default{
...
onShow(){
socket = uni.connectSocket({
url: 'wss://www.example.com/socket', //仅为示例,并非真实接口地址。
complete: ()=> {}
});
socket.onOpen(()=>{console.log('conn')});
socket.onMessage(res=>{...to do});//获取服务器传来的数据,做相应处理
socket.onClose(()=>{console.log('close')});
socket.onError((err)=>{console.log(err)})
},
onHide(){
socket.close();
},...
}
这样的效果是每次打开该页面,都会创建一个长连接,关闭该页面,都会关闭该连接。
如果你希望始终使用一个长连接,那么你可以把onShow()中的部分移到onLoad()中,但是你需要把onHide()中的关闭连接事件删除。
这样从第一次打开该页面开始,长连接就创建,此后始终保持,但是如果小程序进入后台,这个长连接就会自动断开,重新打开小程序,onLoad()事件没有触发创建连接,所以你需要在onShow()中做一个心跳重连监测。
以上是网上提供的思路, 下面是自己实践之后的代码
uniapp代码实现
onLoad(e) {
console.log("on load");
this.loadRoom(e);
},
onShow() {
console.log("onShow");
if(this.hasLogin && this.roomId != null){
this.createWebsocket()
console.log("---connect done--");
}
},
destroyed() {
if(this.socketTask != null){
this.socketTask.closeConnect();
}
if(this.joinSocket != null){
this.joinSocket.closeConnect();
}
if(this.offlineSocket != null){
this.offlineSocket.closeConnect();
}
if(this.checkoutSocket != null){
this.checkoutSocket.closeConnect();
}
},
methods: {
async loadRoom(e){
await this.refreshMyToken();
//根据机型调整房间人员框的高度
this.getPersonBoxMaxHeight();
//获取跳转携带的roomId:好友分享和微信扫一扫
this.roomId = e.roomId;
if(this.roomId === null || this.roomId === undefined || this.roomId === 'null'){
const scene = decodeURIComponent(e.scene)
this.roomId = scene.split("=")[1];
}
//进行登陆判断
if(this.hasLogin === false){
this.$local.set("share_redirect_path", "/pages/index/room?roomId="+this.roomId);
uni.redirectTo({
url:'/pages/login/index'
})
return;
}
//加入房间
this.joinRoom(this.roomId)
//建立连接
this.createWebsocket()
},
//建立ws链接
createWebsocket(){
if(this.socketTask == null){
this.socketTask = new wsRequest(this.serviceUrl + "/jeecg-activiti-gateway/ws/push/"+this.roomId + "/"+ this.userInfo.id, 3000);
this.watchSocket();
}
if(this.offlineSocket == null){
this.offlineSocket = new wsRequest(this.serviceUrl + "/jeecg-activiti-gateway/ws/offline/"+this.roomId + "/"+ this.userInfo.id, 3000);
this.watchOfflineSocket();
}
if(this.joinSocket == null){
this.joinSocket = new wsRequest(this.serviceUrl + "/jeecg-activiti-gateway/ws/join/"+this.roomId + "/"+ this.userInfo.id, 3000);
this.watchJoinSocket();
}
if(this.checkoutSocket == null){
this.checkoutSocket = new wsRequest(this.serviceUrl + "/jeecg-activiti-gateway/ws/checkout/"+this.roomId + "/"+ this.userInfo.id, 3000);
this.watchCheckoutSocket();
}
},
}
实现思路,在onLoad函数,我们就创建了websocket,并且实现了心跳机制检测。
此时,如果小程序退出,将执行destroyed函数将socket关闭
如果重新进入该页面,则会执行onShow函数,重新建立连接。 如此实现了不断连的效果。
参考
uniapp之微信小程序开发WebSocket