JavaScript WebSockets API的机制

JavaScript WebSockets API的机制,javascript,asynchronous,websocket,Javascript,Asynchronous,Websocket,我一直在试图理解一些用于打开websocket的代码: var ws = new WebSocket('ws://my.domain.com'); ws.onopen = function(event) { ... } 我的问题是握手是如何开始的?如果它是在WebSocket构造函数中启动的,那么如果onopen当时没有设置,它将如何被调用?如果WebSocket构造函数创建了一个执行握手的线程,那么在握手结束之前是否必须足够快地定义onopen?如果是这样的话,这听起来有点危险,因为

我一直在试图理解一些用于打开websocket的代码:

var ws = new WebSocket('ws://my.domain.com');
ws.onopen = function(event) {
    ...
}
我的问题是握手是如何开始的?如果它是在WebSocket构造函数中启动的,那么如果onopen当时没有设置,它将如何被调用?如果WebSocket构造函数创建了一个执行握手的线程,那么在握手结束之前是否必须足够快地定义onopen?如果是这样的话,这听起来有点危险,因为如果JS虚拟机速度减慢,那么握手可能会在定义onopen之前完成,这意味着事件不会得到处理。或者设置onopen功能是否会触发握手


有人能给我解释一下API的机制吗?

在当前(同步)代码的执行结束之前,它不会寻找onopen函数。这是因为连接(因此调用
onopen
callback)是异步的。 考虑:

let x = false;
setTimeout(function () {
    x = true
}, 1000);
while(!x){
    console.log('waiting!');
}
那里的
while
循环永远不会结束,但您可能会怀疑它会在一秒钟后结束

如果您通过执行耗时(但同步)的代码来延迟开启功能的初始化,那么这并不危险。另一方面,如果
setTimeout
初始化
onopen
,则无法保证它是否在WebSocket连接准备就绪时定义,因为您无法确定将首先执行哪个回调

如果你在C++中做同样的事情,你会用线程来处理这个问题。在JavaScript中,回调机制不是基于线程的;它的行为就像线程一样(参见上面的无尽while循环)

单线程一次执行一个代码单元和其他代码单元 将一直排队,直到当前代码单元完成执行

资料来源:

重要的是要理解,即使您将某个设置超时时间设置为1s,它也可能在1秒后不执行—如果线程繁忙,它可能永远不会执行

因此,如果您启动WebSocket连接并运行与上面类似的循环,但等待连接准备就绪,那么它可能永远不会结束

对于不熟悉JS的程序员来说,这种行为可能看起来很奇怪。因此,为了可读性,我在可能的情况下,在需要回调的函数的同时或之后立即定义回调

如果您想显式地使用线程和并发执行,请阅读更多关于

参考资料:


    • 您不需要任何设置超时功能。我正在为此使用库,我的代码如下所示:

      var pushstream = new PushStream({
        host: window.location.hostname,
        port: window.location.port,
        modes: "websocket"
      });
      pushstream.onmessage = _manageEvent;
      
      function _manageEvent(eventMessage) {
        console.log(eventMessage);
      }
      
      这让我对WebSocket以及如何用Javascript实现客户端有了深刻的了解:

      以及服务器:


      它有很好的文档记录,我希望能有所帮助:)

      您缺少一点,即实例化和属性设置是同步的,而连接是异步的。如果有人故意延迟设置
      onopen
      参数,这仍然是一个有趣的问题。@Miszy是的,我的意思是
      setTimeout
      -其他同步代码不应该像你说的那样干扰。@OP握手应该在成功连接到服务器并升级协议时发生,不是吗?在这种情况下,它总是在WS-client.JS实例化之后执行所有同步代码之后发生。它是单线程的-它将一次执行所有同步代码;异步代码(如连接到服务器)发生在“后台”,如果成功,则在线程不忙时立即触发
      onopen
      处理程序。我正在Firefox和Chrome上运行一些评测来确保这一点。是的,基本上就是这样。我试图找到一些证据证明“在当前javascript代码完成之前,异步甚至不会启动”,但很明显,异步回调(如
      onopen
      )在同步代码完成执行之前永远不会执行-类似于执行
      setTimeout(function(){},0)
      时发生的情况。只是不要将它与JS1.7的一部分以及已经在Firefox中实现的部分混淆
      =]
      @bfavareto是的,每当我需要等待事件完成冒泡(等待浏览器默认行为和其他事件处理程序完成处理事件)时,我都会在事件处理程序中使用
      setTimeout(fn,0)
      。类似的问题和答案与示例代码如下: