Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid race conditions when assigning custom methods to WebSocket?

When I look at tutorials/documentation about WebSockets I find code like this:

var ws = new WebSocket("ws://localhost:8765/dlt");
ws.onopen = () => {
  // do some very important stuff after connection has been established
  console.log("onopen");
}

But what about race conditions here? Are there somehow avoided in JavaScript?

For example this code (which just assigns onopen after the connection has been opened) will fail:

var ws = new WebSocket("ws://localhost:8765/dlt");
setTimeout(() => {
  ws.onopen = () => {
    // do some very important stuff after connection has been established
    console.log("onopen"); ///  <== won't be called
  }
}, 100);

Can I be sure that the assignment has been done before the connection get's established?

(I tried to extend WebSocket with a custom onopen() method but this doesn't seem to work)

class MyWebSocket extends WebSocket {
  onopen() {
    console.log("onopen()");
    /// do some very important stuff after connection has been established
  }
}
like image 953
frans Avatar asked Oct 18 '25 09:10

frans


2 Answers

You should have a read about javascript's event loop: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#Event_loop

If you look at the section about Run-to-completion, you get this useful explanation:

Each message is processed completely before any other message is processed. This offers some nice properties when reasoning about your program, including the fact that whenever a function runs, it cannot be pre-empted and will run entirely before any other code runs (and can modify data the function manipulates). This differs from C, for instance, where if a function runs in a thread, it may be stopped at any point by the runtime system to run some other code in another thread.

So in your example, the assignment to ws.onopen must be completed before the websocket does anything asynchronous in nature. By putting your assignment inside setTimeout, you are moving it outside of the currently running context, and so it may not be executed before it is required by the websocket.

like image 185
Matt Way Avatar answered Oct 19 '25 22:10

Matt Way


You should rest assured that the example is ok. The Javascript event loop will finish the current task before assuming any other tasks. This means that 1) the WebSocket cannot open the connection (async operation) before the onopen event, 2) the onopen event handler will be called during the following cycles.

Setting the timeout on the other hand will complicate matters, because the events will be called in some order after the current task. This means that that the WebSocket has chance to open the connection before the handler has been set.

like image 27
Sami Hult Avatar answered Oct 19 '25 23:10

Sami Hult