190 lines
3.9 KiB
JavaScript
190 lines
3.9 KiB
JavaScript
/**
|
||
* WebSocket 连接管理工具
|
||
* 职责:建立和维护 WebSocket 连接,接收实时推送消息
|
||
*/
|
||
|
||
var auth = require("./auth");
|
||
var config = require("../config");
|
||
|
||
var socketTask = null;
|
||
var heartbeatTimer = null;
|
||
var reconnectTimer = null;
|
||
var reconnectCount = 0;
|
||
var MAX_RECONNECT = 5;
|
||
var HEARTBEAT_INTERVAL = 30000; // 30秒心跳
|
||
var isConnecting = false;
|
||
|
||
/**
|
||
* 建立 WebSocket 连接
|
||
*/
|
||
function connect() {
|
||
if (socketTask || isConnecting) return;
|
||
|
||
var token = auth.getToken();
|
||
if (!token) {
|
||
console.log("[WS] 未登录,跳过连接");
|
||
return;
|
||
}
|
||
|
||
isConnecting = true;
|
||
var wsUrl = config.wsBaseUrl + "/ws/reminders?token=" + token;
|
||
|
||
console.log("[WS] 开始连接...");
|
||
socketTask = wx.connectSocket({
|
||
url: wsUrl,
|
||
success: function () {
|
||
console.log("[WS] 连接请求已发送");
|
||
},
|
||
});
|
||
|
||
socketTask.onOpen(function () {
|
||
console.log("[WS] 连接成功");
|
||
isConnecting = false;
|
||
// 如果是重连成功,触发提醒事件让页面刷新数据
|
||
if (reconnectCount > 0) {
|
||
console.log("[WS] 重连成功,触发提醒事件刷新数据");
|
||
handleMessage({ type: "reconnected" });
|
||
}
|
||
reconnectCount = 0;
|
||
startHeartbeat();
|
||
});
|
||
|
||
socketTask.onMessage(function (res) {
|
||
try {
|
||
var data = JSON.parse(res.data);
|
||
if (data.type === "reminder") {
|
||
console.log("[WS] 收到提醒:", data.data);
|
||
handleMessage(data.data);
|
||
} else if (data.type === "connected") {
|
||
console.log("[WS] 服务端确认连接:", data.message);
|
||
}
|
||
} catch (e) {
|
||
console.error("[WS] 消息解析失败:", e);
|
||
}
|
||
});
|
||
|
||
socketTask.onClose(function (res) {
|
||
console.log("[WS] 连接关闭:", res);
|
||
isConnecting = false;
|
||
stopHeartbeat();
|
||
socketTask = null;
|
||
attemptReconnect();
|
||
});
|
||
|
||
socketTask.onError(function (err) {
|
||
console.error("[WS] 连接错误:", err);
|
||
isConnecting = false;
|
||
socketTask = null;
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 断开 WebSocket 连接
|
||
*/
|
||
function disconnect() {
|
||
stopHeartbeat();
|
||
stopReconnect();
|
||
|
||
if (socketTask) {
|
||
try {
|
||
socketTask.close();
|
||
} catch (e) {
|
||
// ignore
|
||
}
|
||
socketTask = null;
|
||
}
|
||
isConnecting = false;
|
||
console.log("[WS] 已断开连接");
|
||
}
|
||
|
||
/**
|
||
* 启动心跳定时器
|
||
*/
|
||
function startHeartbeat() {
|
||
stopHeartbeat();
|
||
heartbeatTimer = setInterval(function () {
|
||
if (socketTask) {
|
||
try {
|
||
socketTask.send({ data: "ping" });
|
||
} catch (e) {
|
||
console.error("[WS] 心跳发送失败:", e);
|
||
}
|
||
}
|
||
}, HEARTBEAT_INTERVAL);
|
||
}
|
||
|
||
/**
|
||
* 停止心跳定时器
|
||
*/
|
||
function stopHeartbeat() {
|
||
if (heartbeatTimer) {
|
||
clearInterval(heartbeatTimer);
|
||
heartbeatTimer = null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 尝试重连
|
||
*/
|
||
function attemptReconnect() {
|
||
if (reconnectCount >= MAX_RECONNECT) {
|
||
console.log("[WS] 达到最大重连次数,停止重连");
|
||
return;
|
||
}
|
||
|
||
var delay = Math.min(3000 * (reconnectCount + 1), 15000); // 递增延迟,最大15秒
|
||
console.log("[WS] " + delay / 1000 + "秒后尝试第" + (reconnectCount + 1) + "次重连");
|
||
|
||
reconnectTimer = setTimeout(function () {
|
||
reconnectCount++;
|
||
connect();
|
||
}, delay);
|
||
}
|
||
|
||
/**
|
||
* 停止重连
|
||
*/
|
||
function stopReconnect() {
|
||
if (reconnectTimer) {
|
||
clearTimeout(reconnectTimer);
|
||
reconnectTimer = null;
|
||
}
|
||
reconnectCount = 0;
|
||
}
|
||
|
||
/**
|
||
* 处理收到的消息
|
||
*/
|
||
function handleMessage(data) {
|
||
var app = getApp();
|
||
if (!app) return;
|
||
|
||
// 触发全局事件
|
||
if (app._eventHandlers && app._eventHandlers["reminder"]) {
|
||
app._eventHandlers["reminder"].forEach(function (handler) {
|
||
try {
|
||
handler(data);
|
||
} catch (e) {
|
||
console.error("[WS] 事件处理异常:", e);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 更新角标
|
||
var badge = require("./badge");
|
||
badge.updateTabBadge();
|
||
}
|
||
|
||
/**
|
||
* 获取连接状态
|
||
*/
|
||
function isConnected() {
|
||
return socketTask !== null && !isConnecting;
|
||
}
|
||
|
||
module.exports = {
|
||
connect: connect,
|
||
disconnect: disconnect,
|
||
isConnected: isConnected,
|
||
};
|