im-ui-mobile
Version:
A Vue3.0 + Typescript instant messaging component library for Uniapp
225 lines (188 loc) • 6.02 kB
JavaScript
class WebSocket {
constructor() {
// 私有属性
this.messageCallBack = null;
this.closeCallBack = null;
this.connectCallBack = null;
this.isConnect = false;
this.reconnectTimer = null;
this.lastConnectTime = new Date();
this.socketTask = null;
// 心跳配置
this.heartCheckTimeout = 20000;
this.heartCheckTimer = null;
}
// 私有方法 - 心跳相关
startHeartCheck() {
if (!this.isConnect || !this.socketTask) return;
// console.log('发送WebSocket心跳');
const heartBeat = {
cmd: 1,
data: {}
};
this.sendMessage(JSON.stringify(heartBeat));
}
resetHeartCheck() {
this.clearHeartCheck();
this.heartCheckTimer = setTimeout(() => {
this.startHeartCheck();
}, this.heartCheckTimeout);
}
clearHeartCheck() {
if (this.heartCheckTimer) {
clearTimeout(this.heartCheckTimer);
this.heartCheckTimer = null;
}
}
// 连接 WebSocket
connect(wsurl, token) {
if (this.isConnect) return;
this.lastConnectTime = new Date();
this.socketTask = uni.connectSocket({
url: wsurl,
fail: (e) => {
console.error("WebSocket连接失败:", e);
console.log("10秒后重连...");
this.scheduleReconnect(wsurl, token);
}
});
this.setupSocketEvents(token);
}
// 设置 WebSocket 事件监听
setupSocketEvents(token) {
if (!this.socketTask) return;
this.socketTask.onOpen(() => {
// console.log("WebSocket连接成功");
this.isConnect = true;
// 发送登录命令
const loginInfo = {
cmd: 0,
data: { accessToken: token }
};
this.sendMessage(JSON.stringify(loginInfo));
});
this.socketTask.onMessage((res) => {
try {
const message = JSON.parse(res.data);
this.handleMessage(message);
} catch (error) {
console.error("消息解析失败:", error);
}
});
this.socketTask.onClose((res) => {
// console.log('WebSocket连接关闭', res);
this.handleClose(res);
});
this.socketTask.onError((e) => {
console.error("WebSocket错误:", e);
this.handleClose(e);
});
}
// 处理接收到的消息
handleMessage(message) {
switch (message.cmd) {
case 0: // 登录成功
this.resetHeartCheck();
this.connectCallBack?.();
// console.log('WebSocket登录成功');
break;
case 1: // 心跳响应
this.resetHeartCheck();
break;
default: // 其他消息
// console.log("接收到消息", message);
if (this.messageCallBack) {
this.messageCallBack(message.cmd, message.data);
}
break;
}
}
// 处理连接关闭
handleClose(res) {
this.isConnect = false;
this.clearHeartCheck();
if (this.closeCallBack) {
this.closeCallBack(res);
}
}
// 重新连接
reconnect(wsurl, token) {
console.log("尝试重新连接");
if (this.isConnect) return;
const timeDiff = new Date().getTime() - this.lastConnectTime.getTime();
const delay = timeDiff < 10000 ? 10000 - timeDiff : 0;
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer);
}
this.reconnectTimer = setTimeout(() => {
this.connect(wsurl, token);
}, delay);
}
// 安排重新连接
scheduleReconnect(wsurl, token) {
setTimeout(() => {
this.reconnect(wsurl, token);
}, 10000);
}
// 关闭连接
close(code = 1000) {
if (!this.isConnect || !this.socketTask) return;
this.clearHeartCheck();
this.socketTask.close({
code: code,
complete: () => {
this.isConnect = false;
// console.log("关闭WebSocket连接");
},
fail: (e) => {
console.error("关闭WebSocket连接失败", e);
}
});
}
// 发送消息
sendMessage(message) {
if (!this.isConnect || !this.socketTask) {
console.warn("WebSocket未连接,无法发送消息");
return;
}
this.socketTask.send({ data: message });
}
// 注册连接成功回调
onConnect(callback) {
this.connectCallBack = callback;
}
// 注册消息接收回调
onMessage(callback) {
this.messageCallBack = callback;
}
// 注册连接关闭回调
onClose(callback) {
this.closeCallBack = callback;
}
// 获取连接状态
getIsConnect() {
return this.isConnect;
}
// 获取最后连接时间
getLastConnectTime() {
return this.lastConnectTime;
}
// 设置心跳间隔
setHeartCheckTimeout(timeout) {
this.heartCheckTimeout = timeout;
}
// 销毁实例
destroy() {
this.close();
this.clearHeartCheck();
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer);
this.reconnectTimer = null;
}
this.messageCallBack = null;
this.closeCallBack = null;
this.connectCallBack = null;
this.socketTask = null;
}
}
export default WebSocket;