当前位置:   article > 正文

react自定义hook解决websocket连接,useWebSocket

usewebsocket

react自定义hook,useWebSocket

1、描述

本来项目的告警和消息提醒是用的接口30秒调用一次,这次要改成webSocket传输。

因为前端是用的https,后端用的http,后端的socket只支持ws不支持wss,这里使用了webpack-dev-serverproxy代理了一下。

target:ws目标地址、pathRewrite:地址重写,这里是把/aapp_socket重写成aapp/websocket,ws:是否开启socket,secure: 默认情况下不接收转发到https的服务器上,如果希望支持,可以设置为false ,changeOrigin:是否跨域。差不多就这个意思

  '/aapp_socket': {
                target: `ws://xxx.xxx.xxx/`,
                pathRewrite: {
                    '^/aapp_socket': 'aapp/websocket',
                },
                ws: true,
                secure: false,
                changeOrigin: true,
            },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

使用连接的地址:

`wss://localhost:3000/aapp_socket`;
  • 1

实际的访问的地址就是:

`ws://xxx.xxx.xxx/aapp/websocket
  • 1
2、代码

这里socket,没有配置心跳监测,还是通过我主动去推送来获取信息。这里是获取告警数和消息数量,

首先绑定websocket的事件。主要就是在message的事件中,连接成功后端返回的是sucess,就不做操作。后面就是判断返回的消息格式是否正确,如果不正确就重新连接。

还可以把获取消息的时间间隔,和重新连接间隔,地址等变量抽出来,作为参数传进来。

import {useCallback, useRef, useState, useEffect} from 'react';

const token = window.localStorage.getItem('authorization');
const userId = JSON.parse(window.localStorage.getItem('userInfo') || '')?.id;
// 获取告警数量
const UNREAD_WARN_COUNT = 'UNREAD_WARN_COUNT';
// 获取消息数量
const UNREAD_MSG_COUNT = 'UNREAD_MSG_COUNT';
// 获取消息的间隔
const INT_TIME = 5000;
// websocket状态
const webSocketStatus = {
    CONNECTING: 0,
    OPEN: 1,
    CLOSING: 2,
    CLOSED: 3,
};

const useWebSocket = () => {
    const [reset, setReset] = useState<boolean>(false);
    const socket = useRef<WebSocket>();
    const sendCount = useRef<number>(1);
    const [alarmCount, setAlarmCount] = useState<number>(0);
    const [messageCount, setMessageCount] = useState<number>(0);

    // 开启事件,主动获取数据
    const socketOnOpen = useCallback(() => {
        // 判断连接状态是不是open
        if (socket?.current?.readyState === webSocketStatus.OPEN) {
            // 第一次加载触发一次
            socket?.current?.send(JSON.stringify({businessKey: [UNREAD_MSG_COUNT, UNREAD_WARN_COUNT]}));
        }
        const timer = setInterval(() => {
            if (socket?.current?.readyState === webSocketStatus.OPEN) {
                socket?.current?.send(JSON.stringify({businessKey: [UNREAD_MSG_COUNT, UNREAD_WARN_COUNT]}));
            }
        }, INT_TIME);
        // 返回信息出错清除定时器
        if (sendCount.current === 0) {
            clearInterval(timer);
            setReset(true);
        }
    }, [sendCount]);

    // 关闭事件重新连接
    const socketOnClose = useCallback(() => {
        setReset(true);
    }, []);

    // 出错事件
    const socketOnError = useCallback((err: any) => {
        console.log('err: ', err);
    }, []);

    // 收发信息
    const socketOnMessage = useCallback(
        (e: any) => {
            if (e.data === 'success') return;
            const alarmCountObj = JSON.parse(e.data);
            const paramNameArr = Object.keys(alarmCountObj);
            // 判断返回告警保持连接否则断开连接
            if (paramNameArr[1] === 'UNREAD_WARN_COUNT') {
                sendCount.current += 1;
                setAlarmCount(alarmCountObj.UNREAD_WARN_COUNT);
                setMessageCount(alarmCountObj.UNREAD_MSG_COUNT);
            } else {
                sendCount.current = 0;
            }
        },
        [sendCount],
    );

    // 初始化连接socket
    const socketInit = useCallback(() => {
        try {
            const scoketUrl = `wss://${window.location.host}/aapp_socket/${userId}/${token}`;
            const socketObj = new WebSocket(scoketUrl);
            socketObj.addEventListener('close', socketOnClose);
            socketObj.addEventListener('error', socketOnError);
            socketObj.addEventListener('message', socketOnMessage);
            socketObj.addEventListener('open', socketOnOpen);
            socket.current = socketObj;
            sendCount.current = 1;
        } catch (err) {
            console.log('err: ', err);
        }
    }, [socketOnClose, socketOnError, socketOnMessage, socketOnOpen]);
    // 初始化连接socket
    useEffect(() => {
        socketInit();
    }, [socketInit]);
    // 断线重连
    useEffect(() => {
        if (!reset) return;
        setTimeout(() => {
            socketInit();
            setReset(false);
        }, 30000);
    }, [reset, socketInit]);

    return [alarmCount, messageCount];
};

export default useWebSocket;

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105

使用

 // 告警socket连接
    const [alarmCount, messageCount] = useWebSocket();
  • 1
  • 2
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/770795
推荐阅读
相关标签
  

闽ICP备14008679号