Files
shoot-miniprograms/src/websocket.js
2025-07-25 09:59:54 +08:00

167 lines
4.2 KiB
JavaScript

import { MESSAGETYPES } from "@/constants";
let socket = null;
let heartbeatInterval = null;
let reconnectTimer = null;
/**
* 建立 WebSocket 连接
*/
function createWebSocket(token, onMessage) {
const url = `wss://api.shelingxingqiu.com/socket?authorization=${token}`;
socket = uni.connectSocket({
url,
success: () => {
console.log("websocket 连接成功");
// 启动心跳
startHeartbeat(onMessage);
},
fail: () => {
reconnect(onMessage);
},
});
// 接收消息
uni.onSocketMessage((res) => {
const data = JSON.parse(res.data);
if (data.event === "pong" || !data.data.updates) return;
if (onMessage) onMessage(data.data.updates);
const msg = data.data.updates[0];
if (!msg) return;
if (msg.constructor === MESSAGETYPES.BackToGame) {
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
if (
currentPage.route === "pages/battle-room" ||
currentPage.route === "pages/team-match" ||
currentPage.route === "pages/melee-match"
) {
return;
}
// const lastRoute = uni.getStorageSync("last-route");
// if (
// lastRoute === "pages/battle-room" ||
// lastRoute === "pages/team-match" ||
// lastRoute === "pages/melee-match"
// ) {
// return;
// }
const { battleInfo } = msg;
uni.setStorageSync("current-battle", battleInfo);
console.log("----battleInfo", battleInfo);
// 约战
if (battleInfo.config.battleMode === 1) {
uni.navigateTo({
url: `/pages/battle-room?battleId=${battleInfo.id}`,
});
}
// 排位
if (battleInfo.config.battleMode === 2) {
if (battleInfo.config.mode === 1) {
uni.navigateTo({
url: `/pages/team-match?battleId=${battleInfo.id}`,
});
} else if (battleInfo.config.mode === 2) {
uni.navigateTo({
url: `/pages/melee-match?battleId=${battleInfo.id}`,
});
}
}
} else if (msg.constructor === MESSAGETYPES.MatchOver) {
uni.$emit("game-over");
} else if (msg.constructor === MESSAGETYPES.RankUpdate) {
uni.setStorageSync("latestRank", msg.lvl);
} else if (msg.constructor === MESSAGETYPES.LvlUpdate) {
uni.setStorageSync("latestLvl", msg.lvl);
} else if (msg.constructor === MESSAGETYPES.PaySuccess) {
console.log(1111111, msg);
}
});
// 错误处理
uni.onSocketError((err) => {
console.error("WebSocket 错误", err);
reconnect(onMessage);
});
uni.onSocketClose((result) => {
console.log("WebSocket 已关闭", result);
stopHeartbeat();
reconnect(onMessage);
});
}
/**
* 重连机制
*/
function reconnect(onMessage) {
reconnectTimer && clearTimeout(reconnectTimer);
closeWebSocket(); // 确保关闭旧连接
const token = uni.getStorageSync("token");
if (!token) return;
reconnectTimer = setTimeout(() => {
console.log("reconnecting...");
createWebSocket(token, onMessage);
}, 1000);
}
function closeWebSocket() {
if (socket) {
reconnectTimer && clearTimeout(reconnectTimer);
stopHeartbeat();
try {
socket.close();
} catch (err) {
console.error("关闭WebSocket连接失败", err);
}
socket = null; // 清除socket引用
}
}
function sendHeartbeat(onMessage) {
uni.sendSocketMessage({
data: JSON.stringify({ event: "ping", data: {} }),
success: () => {
// console.log("发送心跳成功");
},
fail: (err) => {
console.error("发送心跳失败", err);
stopHeartbeat();
closeWebSocket(); // 关闭失效的连接
reconnect(onMessage); // 触发重连
},
});
}
/**
* 启动心跳
*/
function startHeartbeat(onMessage) {
stopHeartbeat(); // 防止重复启动
heartbeatInterval = setInterval(() => {
if (socket && socket.readyState === 1) {
// 检查连接状态
sendHeartbeat(onMessage);
}
}, 10000);
}
/**
* 停止心跳
*/
function stopHeartbeat() {
if (heartbeatInterval) {
clearInterval(heartbeatInterval);
heartbeatInterval = null;
}
}
export default {
createWebSocket,
closeWebSocket,
};