关于javascript:记录websocket的使用实现断网重连和心跳机制

21次阅读

共计 2326 个字符,预计需要花费 6 分钟才能阅读完成。

需要

校园平安告警的我的项目,其中一个须要实现的性能就是能够实时告警,简略来说,是后盾通过接管校园里拾音器的关键词告警当前,推送到前端,前端弹窗提醒告警,做出解决。所以采纳了 webSocket 来实现。

根本应用

  1. 这里用正则判断 url 地址的前缀并替换,前面是后盾接口地址,最初是用户 ID(后盾所需参数)
const url = `${baseURL.replace("https://", "ws://").replace("http://", "ws://")}/websocket/api/${userId}`;
  1. 而后在 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]);
  1. 心跳机制性能实现。这里是和后端约定好的,我给他发 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)
    }
}

如有不对的中央,请斧正。欢送大家来一起探讨学习。因为写文章的时候间隔实现性能曾经有一段时间了,所有有些中央可能记得没那么分明了。

正文完
 0