在支付宝小程序中用 websocket 实现实时通信,通过设置心跳时间来监测连接是否存在,若心跳时间内并没接收到任何消息,将自动重连。
小程序 WebSocket 开发文档
此配置是用 多实例的方式 开发的,后续如果有其他socket通信,两者之间互不影响。
如果想用单实例,只要参考文档将对应的方法名修改就可,其他无需改动。
page.js
Page({
data: {
// websocket相关
scoket: null, // websocket实例对象
timeout: 30000, // 超时时间(心跳时间),超过30s无消息推送,重新发送连接
timeoutObj: null, // 计时器对象——向后端发送心跳检测
serverTimeoutObj: null, // 计时器对象——等待后端心跳检测的回复
socketReconnectTimer: null, // 计时器对象——重连
socketReconnectLock: false, // WebSocket重连的锁
socketLeaveFlag: false, // 离开标记(解决 退出登录再登录 时出现的 多次相同推送 问题,出现的本质是多次建立了WebSocket连接)
// websocket相关 (结束)
},
onLoad() {},
// 页面销毁使用
onUnload() {
// 离开标记
this.setData({
socketLeaveFlag: true
})
// 关闭WebSocket
this.data.scoket.close();
},
onShow() {
this.createWebSocket();
},
createWebSocket() {
// websocket启动
const socketTask = my.connectSocket({
url: 'ws://xxxx', // 此 url 仅为示例,开发者可替换自己的 URL
multiple: true // multiple 为 true 则会返回 socketTask
});
// 连接成功建立的回调
socketTask.onOpen(() => {
this.onopenCallback();
});
// 连接发生错误的回调
socketTask.onError(() => {
this.onerrorCallback();
});
// 连接关闭的回调
socketTask.onClose(() => {
this.oncloseCallback();
});
// 接收到消息的回调
socketTask.onMessage(res => {
this.getMessageCallback(res.data);
});
this.setData({
scoket: socketTask
})
},
// websocket重连
socketReconnect() {
let {
socketReconnectLock,
socketReconnectTimer
} = this.data;
if (socketReconnectLock) {
return;
}
socketReconnectLock = true;
socketReconnectTimer && clearTimeout(socketReconnectTimer);
socketReconnectTimer = setTimeout(() => {
console.log("WebSocket:重连中...");
socketReconnectLock = false;
// websocket启动
this.createWebSocket();
}, 4000);
this.setData({
socketReconnectLock,
socketReconnectTimer
})
},
// 连接成功建立的回调
onopenCallback() {
console.log("WebSocket:已连接");
// 心跳检测重置
this.heartReset();
// 心跳检测启动
this.heartStart();
},
// 连接发生错误的回调
onerrorCallback() {
console.log("WebSocket:发生错误");
// websocket重连
this.socketReconnect();
},
// 连接关闭的回调
oncloseCallback() {
console.log("WebSocket:已关闭");
// 心跳检测重置
this.heartReset();
if (!this.data.socketLeaveFlag) {
// 没有离开——重连
// websocket重连
this.socketReconnect();
}
},
// 接收到消息的回调
getMessageCallback(rowInfo) {
// 心跳回复——心跳检测重置
if (rowInfo.data.indexOf("HeartBeat") > -1) {
// 收到心跳检测回复就说明连接正常
this.heartReset(); // 心跳检测重置
this.heartStart(); // 心跳检测启动
} else { // 普通推送——正常处理
// ======= 在此进行逻辑处理 =========
}
},
// 心跳检测重置
heartReset() {
let {
timeoutObj,
serverTimeoutObj
} = this.data;
timeoutObj && clearTimeout(timeoutObj);
serverTimeoutObj && clearTimeout(serverTimeoutObj);
},
// 心跳检测启动
heartStart() {
let {
timeoutObj,
serverTimeoutObj,
scoket,
timeout
} = this.data;
timeoutObj && clearTimeout(timeoutObj);
serverTimeoutObj && clearTimeout(serverTimeoutObj);
timeoutObj = setTimeout(() => {
// 这里向后端发送一个心跳检测,后端收到后,会返回一个心跳回复
scoket.send("HeartBeat");
console.log("发送心跳检测");
serverTimeoutObj = setTimeout(() => {
// 如果超过一定时间还没重置计时器,说明websocket与后端断开了
console.log("未收到心跳检测回复");
// 关闭WebSocket
scoket.close();
}, timeout);
}, timeout);
this.setData({
timeoutObj,
serverTimeoutObj
})
},
});
- 服务连接
- 服务端推送的消息
- 心跳监测,无通信则断开重连