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

Viewed 2004

I am new in react js development and try to integrate WebSocket un my app.

but got an error when I send messages during connection.

my code is

  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);
  };

and got this error

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

Sounds like you're calling ws.send before the socket has completed the connection process. You need to wait for the open event/callback, or check the readyState per docs and queue the send after the readyState changes i.e after the open callback has fired.

Not suggesting you do this, but it might help:

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

As Logan has mentioned my first example is lazy. I just wanted to get OP unblocked and I trusted readers were intelligent enough to understand how to take it from there. So, make sure to handle the available states appropriately, e.g if readyState is WebSocket.CONNECTING then register a listener:

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.
  }
};

I guess you can only send data with ws only if it's already open, and you do not check when it's open or not.

Basically you ask for an openning but you send a message before the server said it was open (it's not instant and you do not know how many time it can take ;) )

I think you should add a variable somithing like let open = false;

and rewrite the onopen

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

and then in your logic you can only send a message if open is equal to true

don't forget the error handling ;)

Related