139 lines
4.3 KiB
React
139 lines
4.3 KiB
React
|
import React, { useEffect, useState } from "react";
|
|||
|
import { View } from "react-native";
|
|||
|
import baseRequest from "../../utils/baseRequest";
|
|||
|
import { get } from "../../utils/storeInfo";
|
|||
|
import { getNoticeCount } from "../../store/reducer";
|
|||
|
import { connect } from "react-redux";
|
|||
|
import "text-encoding";
|
|||
|
var retryInterval = 1000;
|
|||
|
const maxInterval = 60000;
|
|||
|
let interval = null;
|
|||
|
let timer = null;
|
|||
|
var messageQueue = [];
|
|||
|
let socket = null;
|
|||
|
const WebSocketComponent = ({ getData, state, changeCount }) => {
|
|||
|
const [messages, setMessages] = useState([]);
|
|||
|
useEffect(() => {
|
|||
|
// 组件卸载时关闭WebSocket连接
|
|||
|
return () => {
|
|||
|
console.log("卸载了socket");
|
|||
|
socket?.readyState === WebSocket.OPEN && socket?.close();
|
|||
|
clearInterval(interval);
|
|||
|
};
|
|||
|
}, []); // 空依赖数组表示这个effect只在组件挂载时运行一次
|
|||
|
useEffect(() => {
|
|||
|
socket?.close();
|
|||
|
if (state.isSignin) {
|
|||
|
connect_socket();
|
|||
|
} else {
|
|||
|
// changeCount(0);
|
|||
|
clearInterval(interval);
|
|||
|
clearTimeout(timer);
|
|||
|
socket?.close();
|
|||
|
socket = null;
|
|||
|
}
|
|||
|
}, [state]); // 空依赖数组表示这个effect只在组件挂载时运行一次
|
|||
|
async function connect_socket() {
|
|||
|
const appInfo = await get("app_info");
|
|||
|
const base = await baseRequest();
|
|||
|
if (socket && socket?.readyState === 1) return;
|
|||
|
// 创建WebSocket连接
|
|||
|
socket = new WebSocket(
|
|||
|
`${process.env.EXPO_PUBLIC_WEBSOCKET_URL}/ws?b_mid=${base.b_mid}&b_did=${base.b_did}&b_dt=1&b_token=${base.b_token}&b_ch${appInfo.b_ch}`
|
|||
|
);
|
|||
|
socket.onopen = () => {
|
|||
|
console.log("WebSocket connected.");
|
|||
|
retryInterval = 1000;
|
|||
|
// 可以在这里发送消息到服务器,例如:socket.send('Hello Server!');
|
|||
|
if (socket.readyState == WebSocket.OPEN)
|
|||
|
socket.send(JSON.stringify({ t: 1 }));
|
|||
|
};
|
|||
|
|
|||
|
// 处理收到的消息
|
|||
|
socket.onmessage = (event) => {
|
|||
|
if (
|
|||
|
Object.prototype.toString.call(event.data) === "[object ArrayBuffer]"
|
|||
|
) {
|
|||
|
let enc = new TextDecoder("utf-8");
|
|||
|
const view = new Uint8Array(event.data);
|
|||
|
let temp = enc.decode(view);
|
|||
|
try {
|
|||
|
const data = JSON.parse(temp);
|
|||
|
if (data.t === 2 && data.msg.ping_interval) {
|
|||
|
if (socket && socket?.readyState == WebSocket.OPEN)
|
|||
|
socket.send("ping");
|
|||
|
interval = setInterval(() => {
|
|||
|
// 发送 ping 给服务器
|
|||
|
if (socket && socket?.readyState == WebSocket.OPEN)
|
|||
|
socket.send("ping");
|
|||
|
// 响应服务器的 ping
|
|||
|
// socket.on("ping", () => {
|
|||
|
// socket.senrd("pong");
|
|||
|
// });
|
|||
|
}, data.msg.ping_interval * 1000);
|
|||
|
}
|
|||
|
if (data.t === 3) {
|
|||
|
getData(data.msg);
|
|||
|
changeCount(data.msg.d.unread_cnt);
|
|||
|
setMessages((prevMessages) => [...prevMessages, data]);
|
|||
|
}
|
|||
|
} catch (error) {}
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
// 连接关闭时触发
|
|||
|
socket.onclose = async () => {
|
|||
|
clearTimeout(timer);
|
|||
|
const account = await get("account");
|
|||
|
if (state.isSignin && typeof account?.mid === "number") {
|
|||
|
timer = setTimeout(() => {
|
|||
|
if (!state.isSignin) {
|
|||
|
clearTimeout(timer);
|
|||
|
return;
|
|||
|
}
|
|||
|
retryInterval = Math.min(retryInterval * 2, maxInterval);
|
|||
|
try {
|
|||
|
connect_socket();
|
|||
|
} catch (error) {
|
|||
|
console.log(error);
|
|||
|
}
|
|||
|
}, retryInterval);
|
|||
|
}
|
|||
|
// changeCount(0);
|
|||
|
console.log("WebSocket disconnected.");
|
|||
|
};
|
|||
|
|
|||
|
// 连接错误时触发
|
|||
|
socket.onerror = (error) => {
|
|||
|
clearTimeout(timer);
|
|||
|
socket?.close();
|
|||
|
console.error("WebSocket error:", error);
|
|||
|
};
|
|||
|
// 响应服务器的 ping
|
|||
|
// socket.on("ping", () => {
|
|||
|
// socket.send("pong");
|
|||
|
// });
|
|||
|
}
|
|||
|
return (
|
|||
|
<View>
|
|||
|
{/* <Text style={{ fontSize: 24, fontWeight: 'bold' }}>WebSocket Messages</Text>
|
|||
|
<FlatList
|
|||
|
data={messages}
|
|||
|
keyExtractor={(item, index) => index.toString()}
|
|||
|
renderItem={({ item }) => <Text>{item}</Text>}
|
|||
|
/> */}
|
|||
|
</View>
|
|||
|
);
|
|||
|
};
|
|||
|
|
|||
|
const mapDispatchFromProps = (dispatch) => {
|
|||
|
return {
|
|||
|
changeCount: (num) => {
|
|||
|
// 调用dispatch方法,传递actions
|
|||
|
dispatch(getNoticeCount(num));
|
|||
|
},
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
export default connect(null, mapDispatchFromProps)(WebSocketComponent);
|