前端开发websocket的过程是页面初始化后创建了websocket长连接,然后心跳检测,在意外关闭后重重连websocket,离开页面后就对websocket进行销毁,这是很正常的逻辑。
然后在开发过程发现一个问题,离开页面后定时器依然在检测心跳,而且离开后会关闭一次然后被重新连接了,这会导致后台推送数据的时候多次重复出现,甚至在多个不同聊天人之间也出现原来的用户聊天推送(在其它端口推送时,后台根据用户id推送)。
之前前端同事对接出现这个问题就没解决,后台是没问题的,前端同事也不想多干活,反正就是不愿意处理。
现在我自己开发自己的项目,自己图手写了个聊天客服,如下图一样。然后发现了这个问题是普遍存在的,而且就是前端未能清理socket的问题,导致消息混乱。
一开始页面的清理是这样的
beforeDestroy() {
console.log('页面销毁')
this.closeWebSocket();
},
onUnload() {
console.log('页面卸载')
this.closeWebSocket();
},
//关闭清理的方法
closeWebSocket() {
if (this.websocket) {
this.websocket.close();
this.websocket = null;
}
if (this.heartbeatInterval) { // 清除心跳检测定时器
clearInterval(this.heartbeatInterval);
this.heartbeatInterval = null;
}
},
//websocket关闭监听函数
// 处理 WebSocket 关闭
handleWebSocketClose() {
if (this.reconnectTimes < this.maxReconnectTimes) {
setTimeout(() => {
this.reconnectTimes++
this.connectWebSocket()
}, 3000)
} else {
this.isServiceOnline = false
uni.showToast({
title: '客服暂时离线,请留言',
icon: 'none'
})
}
},知道问题是websocket未清理彻底的问题就好办了,解决起来也简单,就是在卸载页面的时候价加上状态,比如leave=true,然后这个状态成立的时候不允许重连即可。根源的问题是重连发生的。修改如下
beforeDestroy() {
console.log('页面销毁')
this.leave = true
this.closeWebSocket();
},
onUnload() {
console.log('页面卸载')
this.leave = true
this.closeWebSocket();
},
// 处理 WebSocket 关闭
handleWebSocketClose() {
if (this.leave){
console.log('页面已离开,不再重连');
return ;
}
if (this.reconnectTimes < this.maxReconnectTimes) {
setTimeout(() => {
this.reconnectTimes++
this.connectWebSocket()
}, 3000)
} else {
this.isServiceOnline = false
uni.showToast({
title: '客服暂时离线,请留言',
icon: 'none'
})
}
},就是在卸载和销毁页面的时候做状态,防止被重连了。
