我怎么能确定我不会错过WebSockets上的“开放”事件?

时间:2013-04-18 15:37:45

标签: javascript websocket

这更像是一个抽象的问题。我怎么能确定我不会错过WebSocket的公开活动?据我了解,浏览器在我调用构造函数后立即开始建立连接,因此如果情况严重,可能会在我的处理程序连接之前触发打开(或错误)事件。

var socket = new WebSocket("ws://www.example.com");
/*Because I'm an unlucky guy, the open-event fires before the next line*/
socket.addEventListener("open", function(event){...});

在这种情况下,我的open-Handler永远不会被调用。很可能这从来不是一个真正的问题,因为建立连接比执行下一行JavaScript需要更长的时间。但是,XMLHttpRequest也可以这样说,推荐的顺序是:

var ajax = new XMLHttpRequest();
ajax.addEventListener("load", function(event){...});
ajax.open();
ajax.send();

这可确保事件不会丢失。为什么WebSocket在这方面有所不同?我是否忽视了某些事情并且错过了这个事件并不是真正的问题?

感谢您对此作出一些澄清。

1 个答案:

答案 0 :(得分:2)

你使用Ajax的第二个例子有一个错误的假设。使用Ajax,在send调用之后放置事件处理程序没有实际问题,只要两者都包含在同一个同步操作集中。发送Ajax请求的Here's a fiddle会烧掉几秒钟(有足够的时间完成提取),然后会附加监听器。正如你所看到的,事件发生得很好。

所以,这没关系:

var ajax = new XMLHttpRequest();
ajax.open();
ajax.send();
ajax.addEventListener("load", function(event){...});

由于浏览器JavaScript的单线程特性,load事件实际上不会在当前代码运行完毕之前触发。 (注意:在旧版浏览器中,这种行为可能有所不同,但它肯定在任何支持WebSockets的浏览器中都能正常工作。)

var ajax = new XMLHttpRequest();
ajax.open();
ajax.send();
setTimeout(function() {
    ajax.addEventListener("load", function(event){...});
}, 1000);

这是因为您在两个异步操作之间创建了竞争条件:setTimeout解析和load事件触发。只要您在触发Ajax请求和设置侦听器之间的延迟处于同一执行中,就不会有“丢失”Ajax事件的风险。

它与WebSockets的工作方式相同 - 只要构造open并将侦听器附加到同一组同步指令中,就不会错过WebSocket事件。 Here's another fiddle执行类似的同步等待WebSocket。正如您所看到的,即使等待几秒钟来附加事件监听器,它仍然会触发。

我不确定“在你采取行动之前附加听众”的做法来自哪里。也许它在旧版浏览器中很重要,或者对于除Ajax之外的某些API也很重要。无论出现这种做法的原因是什么,您实际上并不需要在现代浏览器中遵循它来使用Ajax或WebSockets。