这更像是一个抽象的问题。我怎么能确定我不会错过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在这方面有所不同?我是否忽视了某些事情并且错过了这个事件并不是真正的问题?
感谢您对此作出一些澄清。
答案 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。