JavaScript WebSockets API的机制

Cth*_*utu 7 javascript asynchronous websocket

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

var ws = new WebSocket('ws://my.domain.com');
ws.onopen = function(event) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

我的问题是握手是如何开始的?如果它是在WebSocket构造函数中启动的话,那么如果onopen没有被设置那么它是如何调用的呢?如果WebSocket构造函数创建了一个执行握手的线程,那么在握手结束之前是否必须足够快地定义onopen?如果是这样,那听起来有点危险,因为如果JS虚拟机速度变慢,则可以在定义onopen之前完成握手,这意味着事件不会被处理.或者设置onopen功能会触发握手吗?

有人可以向我解释API的机制吗?

Mic*_*zyn 9

onopen在当前(同步)代码执行结束之前,它不会查找功能.那是因为连接(因此调用onopen回调)是异步的.考虑:

let x = false;
setTimeout(function () {
    x = true
}, 1000);
while(!x){
    console.log('waiting!');
}
Run Code Online (Sandbox Code Playgroud)

while那里的循环永远不会结束,但你可能会怀疑它会在一秒后结束.

如果onopen通过执行耗时(但同步)的代码来延迟函数的初始化,那么它就没有危险了.另一方面,如果你setTimeout初始化onopen那么在WebSockets连接准备就绪时无法保证它是否被定义,因为你无法确定首先执行哪个回调.

如果你在C++中做同样的事情,你会使用线程.在JavaScript中,回调机制不是基于线程的; 它只是表现为线程(参见上面的无尽循环).

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

来源:http://www.slideshare.net/clutchski/writing-asynchronous-javascript-101

重要的是要理解即使你setTimeout有1s的东西它可能在一秒钟后没有执行- 如果线程忙,它可能永远不会被执行.

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

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

如果要显式使用线程和并发执行,请阅读有关Web Workers的更多信息

参考:

  • 类似的问题和答案与示例代码在这里:http://stackoverflow.com/questions/8393092/javascript-websockets-control-initial-connection-when-does-onopen-get-bound (2认同)