将自定义方法分配给 WebSocket 时如何避免竞争条件?

fra*_*ans 4 javascript race-condition websocket

当我查看有关 WebSockets 的教程/文档时,我发现如下代码

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

但这里的竞争条件又如何呢?JavaScript 中是否有某种方式避免了?

例如,此代码(仅在连接打开onopen 后分配)将失败:

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);
Run Code Online (Sandbox Code Playgroud)

我能否确定在建立连接之前分配已完成?

WebSocket(我尝试使用自定义方法进行扩展onopen(),但这似乎不起作用)

class MyWebSocket extends WebSocket {
  onopen() {
    console.log("onopen()");
    /// do some very important stuff after connection has been established
  }
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*Way 5

您应该阅读有关 javascript 事件循环的内容:https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#Event_loop

如果您查看有关 的部分Run-to-completion,您会得到以下有用的解释:

每条消息都会在处理任何其他消息之前完成处理。在推理程序时,这提供了一些很好的属性,包括每当函数运行时,它都不能被抢占,并且将在任何其他代码运行之前完全运行(并且可以修改函数操作的数据)。这与 C 不同,例如,如果一个函数在线程中运行,则运行时系统可能会在任何时候停止它以在另一个线程中运行其他代码。

ws.onopen因此,在您的示例中,必须在 websocket 执行任何异步操作之前完成分配。通过将您的赋值放入setTimeout,您将把它移到当前运行的上下文之外,因此在 websocket 需要它之前它可能不会被执行。