117 lines
2.5 KiB
JavaScript
117 lines
2.5 KiB
JavaScript
let socket = null;
|
||
let heartbeatInterval = null;
|
||
let reconnectCount = 0;
|
||
let reconnectTimer = null;
|
||
|
||
// 重连配置
|
||
const RECONNECT_CONFIG = {
|
||
MAX_COUNT: 999, // 最大重连次数
|
||
INITIAL_DELAY: 2000, // 初始重连延迟(2秒)
|
||
MAX_DELAY: 5000, // 最大重连延迟(5秒)
|
||
};
|
||
|
||
/**
|
||
* 建立 WebSocket 连接
|
||
*/
|
||
function createWebSocket(token, onUpdate, onMessage) {
|
||
const url = `wss://api.shelingxingqiu.com/socket?authorization=${token}`;
|
||
socket = uni.connectSocket({
|
||
url,
|
||
success: () => {
|
||
console.log("websocket 连接成功");
|
||
onUpdate(true);
|
||
reconnectCount = 0; // 重置重连次数
|
||
},
|
||
});
|
||
|
||
// 接收消息
|
||
uni.onSocketMessage((res) => {
|
||
const data = JSON.parse(res.data);
|
||
if (onMessage) onMessage(data.data.updates);
|
||
});
|
||
|
||
// 错误处理
|
||
uni.onSocketError((err) => {
|
||
console.error("WebSocket 错误", err);
|
||
reconnect(token, onMessage);
|
||
});
|
||
|
||
uni.onSocketClose((result) => {
|
||
console.log("WebSocket 已关闭", result);
|
||
onUpdate(false);
|
||
stopHeartbeat();
|
||
reconnect(onUpdate, onMessage);
|
||
});
|
||
|
||
// 启动心跳
|
||
startHeartbeat();
|
||
}
|
||
|
||
/**
|
||
* 重连机制
|
||
*/
|
||
function reconnect(onUpdate, onMessage) {
|
||
if (reconnectCount >= RECONNECT_CONFIG.MAX_COUNT) return;
|
||
|
||
reconnectTimer && clearTimeout(reconnectTimer);
|
||
|
||
const token = uni.getStorageSync("token");
|
||
if (!token) return;
|
||
// 计算重连延迟(指数退避)
|
||
const delay = Math.min(
|
||
RECONNECT_CONFIG.INITIAL_DELAY * Math.pow(2, reconnectCount),
|
||
RECONNECT_CONFIG.MAX_DELAY
|
||
);
|
||
reconnectTimer = setTimeout(() => {
|
||
console.log("reconnecting...");
|
||
createWebSocket(token, onUpdate, onMessage);
|
||
reconnectCount++;
|
||
}, delay);
|
||
}
|
||
|
||
function closeWebSocket() {
|
||
if (socket) {
|
||
// 清理重连定时器
|
||
reconnectCount = 0;
|
||
reconnectTimer && clearTimeout(reconnectTimer);
|
||
stopHeartbeat();
|
||
socket.close();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 启动心跳
|
||
*/
|
||
function startHeartbeat() {
|
||
stopHeartbeat(); // 防止重复启动
|
||
|
||
heartbeatInterval = setInterval(() => {
|
||
if (socket && uni.sendSocketMessage) {
|
||
uni.sendSocketMessage({
|
||
data: {
|
||
event: "ping",
|
||
data: {},
|
||
},
|
||
fail: (err) => {
|
||
console.error("发送心跳失败", err);
|
||
},
|
||
});
|
||
}
|
||
}, 5000);
|
||
}
|
||
|
||
/**
|
||
* 停止心跳
|
||
*/
|
||
function stopHeartbeat() {
|
||
if (heartbeatInterval) {
|
||
clearInterval(heartbeatInterval);
|
||
heartbeatInterval = null;
|
||
}
|
||
}
|
||
|
||
export default {
|
||
createWebSocket,
|
||
closeWebSocket,
|
||
};
|