简体   繁体   English

尝试添加依赖项时出现 websocket 连接错误

[英]Error with websocket connection when trying to add dependencies

I am currently trying to add charts for the graphical part with React in an Electron software.我目前正在尝试在 Electron 软件中使用 React 为图形部分添加图表。 Except that I added interactions with buttons (sections) to insert different data in the graphs depending on the click on one of the sections by the user (variable selectedSection).除了我添加了与按钮(部分)的交互以根据用户对其中一个部分的点击(变量 selectedSection)在图表中插入不同的数据。 So I added in the dependencies of the useEffect() function the chartPMS and chartPFS functions to have access at the selectedSection variable.所以我在useEffect() function 的依赖项中添加了 chartPMS 和 chartPFS 函数以访问 selectedSection 变量。

The useEffect() function receives data continuously through a websocket from a python program. useEffect() function 通过 websocket 从 python 程序连续接收数据。 The problem is that when I run the code via the npm start command, I get a data display with a very high frequency and this error continuously in the console: WebSocket connection to 'ws:<URL>/' failed: WebSocket is closed before the connection is established.问题是,当我通过npm start命令运行代码时,我得到一个非常高频率的数据显示,并且控制台中不断出现此错误: WebSocket connection to 'ws:<URL>/' failed: WebSocket is closed before the connection is established. But the functions did receive changes to the selectedSection variable based on clicks on the different sections.但是这些函数确实收到了基于对不同部分的点击对 selectedSection 变量的更改。

I should point out that I used the useEffect() function in this way before, it worked but I didn't have access to the updated version after clicking on one of the sections of the selectedSection variable:我应该指出,我以前以这种方式使用过useEffect() function,它有效但在单击 selectedSection 变量的其中一个部分后我无法访问更新版本:

  useEffect(() => {
    const socket = new WebSocket('ws://localhost:8000');

    socket.addEventListener('message', (event) => {
      setData(JSON.parse(event.data));

      chartPFS(JSON.parse(event.data));
      chartPMS(JSON.parse(event.data));
    });

  }, []);

I added selectedSection to the dependencies except that it refreshes both panels after clicking on one of the section buttons.我将 selectedSection 添加到依赖项中,除了它在单击其中一个部分按钮后刷新两个面板。

Here are the code:这是代码:

App.js with 2 panels : App.js 有 2 个面板

import React, { useState, useEffect, useRef, useSyncExternalStore } from 'react';
import Modal from './Modal/Modal'
import {Chart as ChartJS,LinearScale,PointElement,LineElement,Tooltip,Legend,Title,CategoryScale,elements} from 'chart.js';
import {Scatter, Line } from 'react-chartjs-2';
import { handleDataClick } from './Modal/Modal';
import { LineChart } from 'recharts';
import 'chart.js/auto';

ChartJS.register(
    CategoryScale,
    LinearScale,
    PointElement,
    LineElement,
    Tooltip,
    Legend,
    Title);

//--------------------------- OPTIONS GRAPHIQUE ----------------------------------//

  export const options5 = {
    elements: {
      line: {
          tension: 0.3,
      },
    },
    responsive: true,
    maintainAspectRatio:false,
    plugins: {
      showLine:true,
      legend: false
    },
  };

//--------------------------- FUNCTION APP() ----------------------------------//
export default function App() {
  let da;
  const [data, setData] = useState(null);
  const [show,setShow] = useState(false);
  const [lastSelectedSection, setLastSelectedSection] = useState(null);
  const h2f5Ref = useRef(null);
  const h2f4Ref = useRef(null);
  const h2f3Ref = useRef(null);
  const h2f2Ref = useRef(null);
  const h2f1Ref = useRef(null);

  const h2m5Ref = useRef(null);
  const h2m4Ref = useRef(null);
  const h2m3Ref = useRef(null);
  const h2m2Ref = useRef(null);
  const h2m1Ref = useRef(null);

  const [selectedDataType, setSelectedDataType] = useState({id:"fs-sec-1",selected:"twist"});
  const [sectionData, setSectionData] = useState({
    "fs-sec-1": { selectedDataType: 'twist' },
    "fs-sec-2": { selectedDataType: 'twist' },
    "fs-sec-3": { selectedDataType: 'twist' },
    "fs-sec-4": { selectedDataType: 'twist' },
    "fs-sec-5": { selectedDataType: 'twist' },
    "ms-sec-1": { selectedDataType: 'twist' },
    "ms-sec-2": { selectedDataType: 'twist' },
    "ms-sec-3": { selectedDataType: 'twist' },
    "ms-sec-4": { selectedDataType: 'twist' },
    "ms-sec-5": { selectedDataType: 'twist' }
  });

  const [selectedSection, setSelectedSection] = useState("s1");
  const [selectedSailP3,setSelectedSailP3]=useState("fs");

  //----------------------- Graphiques Variables initiales  -------------------//


    const [chartDataPFS,setChartDataPFS]=useState({
      datasets: [
          {
              label: 'Draft',
              showLine:true,
              data: [{x:3,y:1},{x:3.5,y:2},{x:5.5,y:3},{x:5.25,y:4},{x:5,y:5}],
              backgroundColor: '#df9305',
              borderColor: '#df9305'
          }]
    });
    const [chartDataPMS,setChartDataPMS]=useState({
      labels:["0","1","2","3","4"],
      datasets: [
          {
              label: 'Draft',
              showLine:true,
              data: [0,2,3,2,0],
              backgroundColor: '#df9305',
              borderColor: '#df9305'
          }]
    });
 
    //----------------------- Graphiques Fonctions mise à jour  -------------------//
  const chartPFS=(d) =>{
    let dataToUse;
    console.log(selectedSection)
    dataToUse=[{x:0,y:0},
      {x:3.3/2,y:d["fs"][selectedSection]["camber"]*0.75},
      {x:3.3,y:d["fs"][selectedSection]["draft"]},
      {x:(10-3.3)/2+3.3,y:d["fs"][selectedSection]["draft"]*0.55},
      {x:10,y:0}];
    setChartDataPFS({
        datasets: [
            {
              label: 'Profile',
              showLine:true,
              maintainAspectRatio:false,
              fill:false,
              data: dataToUse,
              backgroundColor: '#000000',
              borderColor: '#000000'
            }]
    });
  };
  const chartPMS=(d) =>{
    let dataToUse;
    dataToUse=[0,
      d["ms"][selectedSection]["camber"],
      d["ms"][selectedSection]["draft"],
      d["ms"][selectedSection]["draft"],
      0];
    setChartDataPMS({
        labels:[0,1,2,3,4],
        datasets: [
            {
              label: 'Profile',
              maintainAspectRatio:false,
              fill:false,
              data: dataToUse,
              borderColor: '#000000'
            }]
    });
  };

  //----------------------- Fonctions Récupération données au clic  -------------------//

  const handleClick = (id,h2Text) => {
    const sectionId = id;
    setSelectedDataType({id:sectionId,selected:h2Text});
  };
  const handleSectionClick=(section) =>{
    setSelectedSection(section);
  };
  const handleSailP3Click=(sail) =>{
    setSelectedSailP3(sail);
  };

    //----------------------- Mise à jour données  -------------------//
    useEffect(() => {
      const socket = new WebSocket('ws://localhost:8000');

      const handler = (event) => {

        setData(JSON.parse(event.data));
        chart1(JSON.parse(event.data));
        chart2(JSON.parse(event.data));
        chart3(JSON.parse(event.data));
        chart4(JSON.parse(event.data));
        chartPFS(JSON.parse(event.data));
        chartPMS(JSON.parse(event.data));
      };

      socket.addEventListener('message', handler);

      return () => {
        socket.removeEventListener('message', handler);
        socket.close();
      };
    }, [selectedSection]);
  
  
  return (
        <div>
            <div className="home">
                <div className="template-1" id="temp1">
                <div className="panel-1">
                    <div className="panel-header">
                    <h1>FORESAIL data</h1>
                    <i className='bx bx-cog modal-trigger-panel'></i>
                    </div>
                    <div className="panel-body">
                    <div className="sec-5 modal-trigger-data" id="fs-sec-5" onClick={()=>{handleClick("fs-sec-5",h2f5Ref.current.textContent);setShow(true);}} >
                        {data && sectionData["fs-sec-5"].selectedDataType ? <span class="h1" id="h1-fs-s5">{data["fs"]["s5"][sectionData["fs-sec-5"].selectedDataType]}</span> : <span class="h1" id="h1-fs-s5">--</span>}
                        <h2 ref={h2f5Ref}>{sectionData["fs-sec-5"].selectedDataType ? sectionData["fs-sec-5"].selectedDataType.toUpperCase() : "TWIST"}</h2>
                        <h3>s5</h3>
                    </div>
                    <div className="sec-4 modal-trigger-data" id="fs-sec-4" onClick={()=>{handleClick("fs-sec-4",h2f4Ref.current.textContent);setShow(true);}}>
                        {data && sectionData["fs-sec-4"].selectedDataType ? <span class="h1" id="h1-fs-s4">{data["fs"]["s4"][sectionData["fs-sec-4"].selectedDataType]}</span> : <span class="h1" id="h1-fs-s4">--</span>}
                        <h2 ref={h2f4Ref}>{sectionData["fs-sec-4"].selectedDataType ? sectionData["fs-sec-4"].selectedDataType.toUpperCase() : "TWIST"}</h2>
                        <h3>s4</h3>
                    </div>
                    <div className="sec-3 modal-trigger-data" id="fs-sec-3" onClick={()=>{handleClick("fs-sec-3",h2f3Ref.current.textContent);setShow(true);}}>
                        {data && sectionData["fs-sec-3"].selectedDataType ? <span class="h1" id="h1-fs-s3">{data["fs"]["s3"][sectionData["fs-sec-3"].selectedDataType]}</span> : <span class="h1" id="h1-fs-s3">--</span>}
                        <h2 ref={h2f3Ref}>{sectionData["fs-sec-3"].selectedDataType ? sectionData["fs-sec-3"].selectedDataType.toUpperCase() : "TWIST"}</h2>
                        <h3>s3</h3>
                    </div>
                    <div className="sec-2 modal-trigger-data" id="fs-sec-2" onClick={()=>{handleClick("fs-sec-2",h2f2Ref.current.textContent);setShow(true);}}>
                        {data && sectionData["fs-sec-2"].selectedDataType ? <span class="h1" id="h1-fs-s2">{data["fs"]["s2"][sectionData["fs-sec-2"].selectedDataType]}</span> : <span class="h1" id="h1-fs-s2">--</span>}
                        <h2 ref={h2f2Ref}>{sectionData["fs-sec-2"].selectedDataType ? sectionData["fs-sec-2"].selectedDataType.toUpperCase() : "TWIST"}</h2>
                        <h3>s2</h3>
                    </div>
                    <div className="sec-1 modal-trigger-data" id="fs-sec-1" onClick={()=>{handleClick("fs-sec-1",h2f1Ref.current.textContent);setShow(true);}}>
                        {data && sectionData["fs-sec-1"].selectedDataType ? <span class="h1" id="h1-fs-s1">{data["fs"]["s1"][sectionData["fs-sec-1"].selectedDataType]}</span> : <span class="h1" id="h1-fs-s1">--</span>}
                        <h2 ref={h2f1Ref}>{sectionData["fs-sec-1"].selectedDataType ? sectionData["fs-sec-1"].selectedDataType.toUpperCase() : "TWIST"}</h2>
                        <h3>s1</h3>
                    </div>
                    </div>
                </div>
                <div class="panel-5">
                    <div class="panel-header">
                        <h1>SAILS sections</h1>
                        <i class='bx bx-cog modal-trigger-panel'></i>
                    </div>
                    <div class="panel-body">
                        <div class="profil-container" style={{display: "flex", flexDirection: "row"}}>
                            <div style={{width: "50%",height: "100%"}}>
                                <Scatter options={options5} data={chartDataPFS}/>
                            </div>
                            <div style={{width: "50%",height: "100%"}}>
                                <Line options={options5} data={chartDataPMS}/>
                            </div>
                        </div>
                        <div class="button-sec">
                            <input type="submit" value="Section 5" class={`section5 ${selectedSection === "s5" ? 'active' : ''}`} onClick={()=>{handleSectionClick("s5")}}/>
                            <input type="submit" value="Section 4" class={`section4 ${selectedSection === "s4" ? 'active' : ''}`} onClick={()=>{handleSectionClick("s4")}}/>
                            <input type="submit" value="Section 3" class={`section3 ${selectedSection === "s3" ? 'active' : ''}`} onClick={()=>{handleSectionClick("s3")}}/>
                            <input type="submit" value="Section 2" class={`section2 ${selectedSection === "s2" ? 'active' : ''}`} onClick={()=>{handleSectionClick("s2")}}/>
                            <input type="submit" value="Section 1" class={`section1 ${selectedSection === "s1" ? 'active' : ''}`} onClick={()=>{handleSectionClick("s1")}}/>
                        </div>
                        <div class="button-sail">
                            <input type="submit" value="Foresail" class="btn-hs modal-trigger-hs"/>
                            <input type="submit" value="Mainsail" class="btn-ms modal-trigger-ms"/>                            
                        </div>
                    </div>
                </div>
                </div>
                <Modal onClose={() => setShow(false)} show={show} Data={selectedDataType} sectionData={sectionData} setSectionData={setSectionData}/>
            </div>
        </div> 
  );
}

Python : Python :

import asyncio
import random
import datetime
import websockets
import json

sv={"fs":{
    "s5":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
    "s4":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
    "s3":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
    "s2":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
    "s1":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
    },
    "ms":{
    "s5":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
    "s4":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
    "s3":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
    "s2":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
    "s1":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},    
    }}

async def handler(websocket, path):
    while True:
        #log_decoder()
        for key1 in sv:
            for key2 in sv[key1]:
                sv[key1][key2]["entry"] = random.randint(1, 10)
                sv[key1][key2]["cfwd"] = random.randint(1, 10)
                sv[key1][key2]["camber"] = random.randint(1, 10)
                sv[key1][key2]["draft"] = random.randint(1, 4)
                sv[key1][key2]["caft"] = random.randint(1, 10)
                sv[key1][key2]["exit"] = random.randint(1, 10)
                sv[key1][key2]["twist"] = random.randint(1, 10)
                sv[key1][key2]["saglat"] = random.randint(1, 10)
                sv[key1][key2]["saglong"] = random.randint(1, 10)        
        #data = [random.randint(0, 20) for _ in range(10)]
        await websocket.send(json.dumps(sv))
        await asyncio.sleep(1)

start_server = websockets.serve(handler, "localhost", 8000)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

Regards,问候,

If you set the dependency to be selectedSection it should solve your problem.如果您将依赖项设置为selectedSection ,它应该可以解决您的问题。 This is because that when you set the dependency to the functions it will rerender basically as fast as your computer allows, but if you set it to selectedSection it only rerender when that is updated and the correct value is included.这是因为当您将依赖项设置为函数时,它基本上会按照您的计算机允许的速度重新呈现,但是如果您将其设置为selectedSection ,它只会在更新并包含正确的值时重新呈现。

Briefly scanning over your code, it seems as if the problem may be caused by the way your useEffect() method handles the WebSocket connection.简要扫描您的代码,似乎问题可能是由您的useEffect()方法处理 WebSocket 连接的方式引起的。 When dealing with websockets, the error message "WebSocket connection failed: WebSocket being closed before the connection is established" typically refers to a websocket that is being closed before it has a chance to establish a connection.在处理websockets时,报错信息"WebSocket connection failed: WebSocket being closed before the connection is established"通常是指websocket在有机会建立连接之前正在关闭。

One other thing that might be causing this is that you're initiating a new WebSocket connection each time the component re-renders, which could also be the culprit.可能导致此问题的另一件事是每次组件重新呈现时您都会启动一个新的 WebSocket 连接,这也可能是罪魁祸首。 I've encountered this issue a few times in one of my projects;我在我的一个项目中遇到过几次这个问题; however, putting the WebSocket connection outside of useEffect() so that it's only instantiated once fixed the issue.但是,将 WebSocket 连接放在useEffect()之外,以便它仅在解决问题后实例化。

One last thing I would try is using useEffect() with an empty array as the dependencies if you only intend to run the connection once on mount.如果您只打算在挂载时运行一次连接,我要尝试的最后一件事是使用带有空数组的useEffect()作为依赖项。 So when you want to update selectedSection , you can use setSelectedSection to update the state, and then use that state value in useEffect() to determine how to handle the data coming in over the websocket.因此,当您想要更新selectedSection时,可以使用setSelectedSection来更新 state,然后在useEffect()中使用该 state 值来确定如何处理通过 websocket 传入的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 尝试连接时取消 WebSocket 连接 (JavaScript) - Cancel WebSocket connection when trying to connect (JavaScript) 连接建立错误:尝试建立并连接到Websocket服务器时,抛出net :: ERR_SSL_PROTOCOL_ERROR - Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR is thrown when trying establish and connect to a websocket server 建立 websocket 连接时出错 - Error in establishing websocket connection WebSocket 使用 Django 创建聊天应用程序时出现连接错误 - WebSocket connection error when creating a chat application with Django https网站中的websocket连接错误 - websocket connection error in https website WebSocket 连接失败:连接建立错误 - WebSocket Connection failed: error in connection establishment WebSocket 连接失败。 WebSocket 握手期间出错 - socketjs - WebSocket connection failed. Error during WebSocket handshake - socketjs 尝试在图表上添加positionLine时出错 - Error when trying to add positionLine on chart 尝试在jQuery中将类添加到父级时出错 - Error when trying to add class to parent in jQuery 浏览器关闭 WebSocket 连接,错误 1006 在我在 OpenVPN 后面时建立后一秒 - Browser closes WebSocket connection with error 1006 one second after it is established when I'm behind OpenVPN
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM