8

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

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

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

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

4

2 回答 2

10

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

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

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

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

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

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

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

重要的是要了解,即使您在 1 秒内执行某些操作setTimeout,它也可能不会在一秒钟后执行- 如果线程很忙,它可能永远不会被执行。

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

对于不熟悉 JS 的程序员来说,这种行为可能看起来很奇怪。因此,为了便于阅读,我尽可能在需要它们的函数的同时或紧随其后定义回调。

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

参考:

于 2013-01-16T20:41:14.377 回答
1

您不需要任何 setTimeout 功能。我为此使用了一个库,我的代码如下所示:

var pushstream = new PushStream({
  host: window.location.hostname,
  port: window.location.port,
  modes: "websocket"
});
pushstream.onmessage = _manageEvent;

function _manageEvent(eventMessage) {
  console.log(eventMessage);
}

这让我对 websockets 以及如何在 Javascript 中实现客户端有了深入的了解:https ://github.com/wandenberg/nginx-push-stream-module/blob/master/misc/js/pushstream.js

还有服务器:https ://github.com/wandenberg/nginx-push-stream-module/

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

于 2013-05-23T09:54:58.770 回答