发送几条消息后,WebSocket readyState 停留在 0

WebSocket readyState stuck at 0 after a couple of messages are sent

我正在尝试使用网络套接字开发一个实时聊天应用程序并做出反应,但在我尝试提交几条消息(大约 30 条)后,网络套接字卡在了连接状态。我设置了它,所以当它发送消息时它禁用了发送按钮以防止用户过快地发送垃圾消息,但不幸的是我仍然遇到同样的问题。

// id is a uuid() string
const ws = new WebSocket(`ws://localhost:3001/chat/${id}`);

useEffect(() => {
        ws.onmessage = function(evt){
            try{
                const user_id = parseInt(evt.data.split("")[0]);
                const message = evt.data.slice(1);
                const currentTime = new Date();
                const currentUTC = currentTime.toUTCString();
                const timestamp = new Date(currentUTC);
                setMessages(messages => [...messages, {user_id, message, timestamp}])
            } catch(e){
                console.log(e);
            }
        }

        ws.onclose = function(evt){
            console.log("DISCONNECTED!!")
            ws.close();
        }

        ws.onerror = function(evt){
            console.log(evt);
            ws.close();
        }
    }, []);


useEffect(() => {
        async function postMessageToAPI() {
            
            const messsageToSend = {
                unique_id: id,
                message: formData.message, 
                user_id: user.id, 
                group_chat_id: room.id
            }
            // Convert to unviersal time UTC and send it to database
            let currentUTC = new Date();
            currentUTC.toUTCString();
            messsageToSend.timestamp = currentUTC;

            await AnonChatApi.sendChatMessage(messsageToSend);
        }

        if(sendMessage){
            ws.onopen = function(){
                // add user_id to the start of the message string
                const message = `${user.id}` + formData.message;
                ws.send(message);
            }
            postMessageToAPI();
            resetFormData();
            setTimeout(() => {
                setSendMessage(false)
            }, 1000);
        }
    }, [sendMessage]);

const goBackHome = () => {
        ws.close();
        history.push('/');
    }

我看你在用 Hooks,所以你肯定也在用 Function Components。 我是否认为初始化 websocket 的代码是正确的

const ws = new WebSocket(`ws://localhost:3001/chat/${id}`);

在函数的顶部?

提醒一下,无论何时渲染组件,定义函数组件的函数都是 运行。任何未保存在状态中的内容都会丢失。这包括您的 websocket - 每次渲染都会创建一个新的,您的异步函数可能会在旧的 websocket 上发送数据(来自以前的渲染),并且 React 可能会在控制台警告您存在内存泄漏。

useEffect 是这里的正确方法,但是 websocket 也需要保存在状态中。

YourFunctionComponent() {
  const [ws, setWs] = useState(null);

  useEffect(() => {
    if (ws == null) {
      setWs(new WebSocket(`ws://localhost:3001/chat/${id}`));
    }
    return () => {
      // A function returned from useEffect will
      // get called on component unmount. 
      // Use this function to clean up your connection and 
      // close your websocket!

      // clean up, e.g.
      // ws.send('closing due to unmount!');
      
      ws.close();
      setWs(null);
    }
  }, [ws, setWs]);


  // Add `ws` as a dependency in the useEffect()s you posted above
  useEffect(() => {
    ws.onmessage = function(evt){
[--snip--]
    }
  }, [ws]);

  useEffect(() => {
    async function postMessageToAPI() {
[--snip--]
    }
  }, [sendMessage, ws]);
}