我如何确定不会错过 WebSockets 上的“打开”事件? [复制]
Posted
技术标签:
【中文标题】我如何确定不会错过 WebSockets 上的“打开”事件? [复制]【英文标题】:How can I be sure I don't miss the "open" event on WebSockets? [duplicate] 【发布时间】:2013-04-18 15:37:45 【问题描述】:这确实是一个抽象的问题。我如何确保不会错过 WebSocket 的 open 事件?据我了解,只要我调用构造函数,浏览器就会开始建立连接,因此如果出现问题,可能会在连接这些事件的处理程序之前触发一个打开(或错误)事件。
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】:您使用 Ajax 的第二个示例有一个错误的假设。使用 Ajax,将您的事件处理程序放在 send
调用之后没有实际问题,只要两者都包含在同一个同步操作集中。 Here's a fiddle 发送 Ajax 请求,消耗几秒钟(完成获取的大量时间),然后 附加侦听器。如您所见,事件触发得很好。
所以,没关系:
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 的工作方式相同 - 只要您构造 WebSocket
并将侦听器附加到相同的同步指令集中,您就不会错过 open
事件。 Here's another fiddle 对 WebSocket 进行类似的同步等待。如您所见,即使在等待几秒钟后附加事件侦听器,它仍然会触发。
我不确定“在行动之前先吸引听众”的做法从何而来。也许它在旧浏览器中很重要,或者对于 Ajax 以外的某些 API 很重要。无论出现这种做法的原因是什么,您实际上都不需要在现代浏览器中为 Ajax 或 WebSockets 坚持它。
【讨论】:
谢谢,这正是我正在寻找的答案!我知道我忽略了一些东西,但我就是无法指望它。我从没想过缺少多线程会使整个事情变得不成问题。 奇怪的是,在那个小提琴中我从来没有收到“打开”警报:( @CiprianTomoiaga 什么浏览器?在您的控制台中,您是否看到任何关于无法到达echo.websocket.org
的网络错误?它在 Chrome 中仍然适用于我。以上是关于我如何确定不会错过 WebSockets 上的“打开”事件? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
Tomcat 上的 Websockets:如何干净地关闭服务器?