需要
校园平安告警的我的项目,其中一个须要实现的性能就是能够实时告警,简略来说,是后盾通过接管校园里拾音器的关键词告警当前,推送到前端,前端弹窗提醒告警,做出解决。所以采纳了webSocket来实现。
根本应用
- 这里用正则判断url地址的前缀并替换,前面是后盾接口地址,最初是用户ID(后盾所需参数)
const url = `${baseURL.replace("https://", "ws://").replace("http://", "ws://")}/websocket/api/${userId}`;
- 而后在useEffect中写入连贯,组件销毁的时候再去敞开连贯。
// webSocket 连贯状态const [isConnect, setIsConnect] = useState<number>(-1);const [socket, setSocket] = useState<any>(null);useEffect(() => { const ws = new WebSocket(url); setSocket(ws); return () => { ws.close(); };}, []);
3.在新的useEffect中定义各个状态的回调。
useEffect(() => { if (socket) { //onopen是webSocket连贯胜利后的回调,能够在这里打印一下,如果胜利打印,则代表连贯胜利 socket.onopen = () => { setIsConnect(1) }; //WebSocket协定只容许字符串或二进制类型的数据传输 //onmessage是承受到数据后的回调 socket.onmessage = (data: string) => acceptMessage(data); //onclose是连贯敞开后的回调。前面均为自定义函数,能够在新的函数里写本人的业务逻辑 socket.onclose = () => webSocketOnClose(); socket.onerror = () => webSocketOnError(); }}, [socket]);
4.接管音讯,在这一步,后盾推送音讯过去后打印进去,就代表胜利接管,能够写本人业务逻辑了。
const acceptMessage = ({ data }: string) => { console.log(data)}
5.前端断网重连性能,场景大略就是如果前端网络中断了当前,websocket就断开了,这时候网络复原后,是不会主动重连的,所以加上这两个监听就能够实现了。
const initWebSocket = () => { const ws = new WebSocket(url); setSocket(ws); console.log('socket初始化')} // 断网重连useEffect(() => { const handleOnline = () => initWebSocket(); const handleOffline = () => { if (socket) { socket.close(); setIsConnect(0); } }; window.addEventListener("online", handleOnline); window.addEventListener("offline", handleOffline); return () => { window.removeEventListener("online", handleOnline); window.removeEventListener("offline", handleOffline); };}, [socket]);
- 心跳机制性能实现。这里是和后端约定好的,我给他发ping,他承受到当前给我返pong,这种状况能够认定是链接胜利状态的。因为过后思考能够用onclose事件去重连。然而会呈现一个问题就是,当组件卸载后,链接会敞开,这个时候onclose监听到了,他又会去做个新的链接,会导致后盾有效链接越来越多。所以采纳了手写心跳的形式。
useEffect(() => { if (socket) { socket.onopen = () => { setIsConnect(1) }; socket.onmessage = (data: string) => acceptMessage(data); socket.onclose = () => webSocketOnClose(); socket.onerror = () => webSocketOnError(); // 心跳机制 实现思路,每跟后盾发一次ping,前端计数+1,后盾返回pong,计数清零,如没有返回pong,则计数累加,当计数大于5后,从新链接。 const heartbeatInterval = setInterval(() => { if (socket.readyState === WebSocket.OPEN) { socket.send(`${userId},PING`); setPingNum(() => pingNum + 1) } }, 5000); return () => clearInterval(heartbeatInterval); }}, [socket, pingNum]);useEffect(() => { if (pingNum > 5) { initWebSocket(); }}, [pingNum])const acceptMessage = ({ data }: any) => { const acceptData = JSON.parse(data); if (acceptData === "PONG") { setPingNum(0) }}