DEV Community

Discussion on: Wait for the WebSocket connection to be open, before sending a message

Collapse
 
thepeoplesbourgeois profile image
Josh

Nice way of solving the race condition in your code! 👍

With reuse of the socket.send() method being a critical aspect of websocket functionality, it makes sense that you wouldn't want to have it be called in socket.onopen just the one time. Looking at how your code is structured, I wonder if you could avoid (or simplify) the timeout logic by resolving the promise once a true value is seen on checking for the socket to be open?

function waitForOpenSocket(socket) {
  return new Promise((resolve, _reject) => {
    while (socket.readyState !== socket.OPEN) { /* no-op */ }
    return resolve()
  })
}

async function sendMessage(socket, msg) {
  await waitForOpenSocket(socket)
  socket.send(msg)
}
Enter fullscreen mode Exit fullscreen mode

I came into Javascript after async/await had already been standardized, and haven't worked much with the Promise API directly, so I don't actually know whether my while loop gives program execution back to the rest of the app, or makes the app hang until the socket is open... but it should let the app continue working, if I understand promises as much as I think I do.

Collapse
 
ndrbrt profile image
Andrea Bertoloni • Edited

Well, my point is: since the open state depends on a network request that takes a certain amount of time to be completed and could eventually fail, I want my code to check the status only at given intervals; furthermore, since the request could fail, I don't to want to end up stuck in that loop forever, but eventually break it after n checks.

You could use async/await, but sometimes I just feel more comfortable using a Promise instead (after all an async function is just a sort of a shortcut that returns a Promise)

Collapse
 
fabiwlf profile image
Fabian Wolf • Edited

The while loop stops the code execution in my case.

Better use something like this, works fine for me:

const waitForOpenSocket = (socket) => {
  return new Promise((resolve) => {
    if (socket.readyState !== socket.OPEN) {
      socket.on("open", _ => {
        resolve();
      });
    } else {
      resolve();
    }
  });
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
engelmav profile image
Vincent Engelmann • Edited

This was the best solution for me. Minor tweak, this looks like it's for socketio. The following is for vanilla websockets:


async waitForOpenSocket(socket) {
    return new Promise((resolve) => {
      if (socket.readyState !== socket.OPEN) {
        socket.addEventListener("open", (_) => {
          resolve();
        })
      } else {
        resolve();
      }
    });
  }
Enter fullscreen mode Exit fullscreen mode