无法在“WebSocket”上执行“发送”:仍处于 CONNECTING 状态

Posted

技术标签:

【中文标题】无法在“WebSocket”上执行“发送”:仍处于 CONNECTING 状态【英文标题】:Failed to execute 'send' on 'WebSocket': Still in CONNECTING state 【发布时间】:2021-07-08 14:04:11 【问题描述】:

我是 react js 开发的新手,并尝试将 WebSocket 集成到我的应用程序中。

但在连接过程中发送消息时出现错误。

我的代码是

  const url = `$wsApi/ws/chat/$localStorage.getItem("sID")/$id/`;


  const ws = new WebSocket(url);

  ws.onopen = (e) => 
    console.log("connect");
  ;

  ws.onmessage = (e) => 
    const msgRes = JSON.parse(e.data);
    setTextMessage(msgRes.type);
    // if (msgRes.success === true) 
    //   setApiMessagesResponse(msgRes);
    // 
    console.log(msgRes);
  ;
  // apiMessagesList.push(apiMessagesResponse);

  // console.log("message response", apiMessagesResponse);
  ws.onclose = (e) => 
    console.log("disconnect");
  ;

  ws.onerror = (e) => 
    console.log("error");
  ;

  const handleSend = () => 
    console.log(message);
    ws.send(message);
  ;

得到了这个错误

Failed to execute 'send' on 'WebSocket': Still in CONNECTING state

【问题讨论】:

apiMessagesResponse 声明在哪里? @Pointy 这是我用来设置 API 响应的状态...与 websocket 无关 【参考方案1】:

听起来您在套接字完成连接过程之前调用了ws.send。您需要等待open 事件/回调,或检查readyState 每docs 并在readyState 更改后(即open 回调已触发后)排队发送。

不建议您这样做,但它可能会有所帮助:

const handleSend = () => 
  if (ws.readyState === WebSocket.OPEN) 
    ws.send()
   else 
    // Queue a retry
    setTimeout(() =>  handleSend() , 1000)
  
;

正如洛根所说,我的第一个例子是懒惰的。我只是想让 OP 畅通无阻,我相信读者足够聪明,能够理解如何从那里获取它。因此,请确保适当地处理可用状态,例如如果 readyStateWebSocket.CONNECTING 然后注册一个监听器:

const handleSend = () => 
  if (ws.readyState === WebSocket.OPEN) 
    ws.send()
   else if (ws.readyState == WebSocket.CONNECTING) 
    // Wait for the open event, maybe do something with promises
    // depending on your use case. I believe in you developer!
    ws.addEventListener('open', () => handleSend())
   else 
    // etc.
  
;

【讨论】:

不客气。我改进了这个例子,使我的意图更加清晰。 为什么要setTimeout 而不是监听open 事件?使用setTimeout 是很糟糕的。 您的所有问题都在我的回答中得到解决。【参考方案2】:

我猜你只能在已经打开的情况下使用 ws 发送数据,并且你不检查它何时打开。

基本上你要求打开,但你在服务器说它打开之前发送了一条消息(它不是即时的,你不知道它需要多少时间;))

我认为您应该添加一个类似于let open = false; 的变量

并重写onopen

ws.onopen = (e) => 
    open = true;
    console.log("connect");
  ;

然后在您的逻辑中,您只能在 open 等于 true 时发送消息

不要忘记错误处理;)

【讨论】:

顺便说一句,您没有向我们展示后端,因此此消息仅在后端完美的情况下才会显示,否则它可能会因后端错误而无法打开 后端由其他开发人员开发。您是在询问后端响应吗? @hannah 不,我只是告诉你,你没有提到后端不是你的,所以未来的问题可能来自你的背后,所以不是你展示给我们的代码,而是你的代码确实表明我们错过了对应该是它的 ws 开放的验证:P 感谢您的支持。我已经解决了我的问题:)

以上是关于无法在“WebSocket”上执行“发送”:仍处于 CONNECTING 状态的主要内容,如果未能解决你的问题,请参考以下文章

未捕获的 InvalidStateError:无法在“WebSocket”上执行“发送”:

IIS WebSocket Ping pong 非空闲时发送

Websockets至少在一台机器上工作

Java Server,html客户端,无法向服务器发送消息

Android服务在其仍处于活动状态时停止后台处理

websocket前端发送一个消息 后端还没执行完 收不到第二条消息