dbe*_*ham 28 javascript html5 websocket
两个相关的问题可能更多地源于我对浏览器预解析javascript的方式缺乏了解:
var ws = new WebSocket("ws://ws.my.url.com");
ws.onOpen = function() { ... };
Run Code Online (Sandbox Code Playgroud)
似乎没有办法直接控制a的初始化WebSocket
,除了将它包装在回调中,所以我假设一旦javascript代码被加载并创建到构造函数就会创建连接?
该onOpen
物业何时附加ws
?是否存在竞争条件的可能性(如果由于某种原因,您在套接字的定义和onOpen
?的定义之间有一些代码),那么onOpen
在建立连接之前/之后是不可判定地绑定的(我知道您可以选择检查ws.readyState
) .补充一点,是WebSocket握手阻塞吗?
我意识到这一切都是目前的草案,可能依赖于实现,我可能已经错过了一些令人眼花缭乱的显而易见的事情,但是在我的互联网搜索/浏览草案w3c规范时我看不出任何特别相关的信息,所以对我的理解有任何帮助websockets/javascript的内部工作非常感谢!
leg*_*ter 32
JavaScript是单线程的,这意味着在当前执行范围完成且网络执行有机会运行之前,无法建立网络连接.执行范围可以是当前函数(connect
下例中的函数).所以,onopen
如果你在使用setTimeout时很晚就绑定它,你可能会错过这个事件,例如在这个例子中你可能会错过这个事件:
查看:http://jsbin.com/ulihup/edit#javascript,html,live
码:
var ws = null;
function connect() {
ws = new WebSocket('ws://ws.pusherapp.com:80/app/a42751cdeb5eb77a6889?client=js&version=1.10');
setTimeout(bindEvents, 1000);
setReadyState();
}
function bindEvents() {
ws.onopen = function() {
log('onopen called');
setReadyState();
};
}
function setReadyState() {
log('ws.readyState: ' + ws.readyState);
}
function log(msg) {
if(document.body) {
var text = document.createTextNode(msg);
document.body.appendChild(text);
}
}
connect();
Run Code Online (Sandbox Code Playgroud)
如果您运行该示例,您可能会看到永远不会输出'onopen called'日志行.这是因为我们错过了这个活动.
但是,如果您将事件new WebSocket(...)
的绑定和绑定保持onopen
在相同的执行范围内,那么您将无法错过该事件.
有关scope of execution
这些排队,计划和处理的更多信息以及如何排序,请查看John Resig关于JavaScript中Timers的帖子.
TL;DR - 标准规定可以“在 [JS] 事件循环运行时”打开连接(例如通过浏览器的 C++ 代码),但是触发事件open
必须在 JS 事件循环中排队,这意味着任何onOpen
回调注册在new WebSocket(...)
保证执行的同一执行块中,即使连接在当前执行块仍在执行时打开。
根据HTML 标准中的WebSocket 接口规范(重点是我的):
调用构造函数
WebSocket(url, protocols)
时,必须运行以下步骤:
- 让
urlRecord
是应用 URL 解析器的结果url
。- 如果
urlRecord
失败,则抛出一个“SyntaxError
”DOMException
。- 如果
urlRecord
方案不是“ws
”或“wss
”,则抛出“SyntaxError
”DOMException
。- 如果
urlRecord
的片段非空,则抛出一个 "SyntaxError
"DOMException
。- 如果
protocols
是字符串,则设置protocols
为仅包含该字符串的序列。- 如果 中的任何值
protocols
出现多次或无法满足构成 Sec-WebSocket-Protocol 字段值的元素的要求(如WebSocket 协议所定义) ,则抛出“SyntaxError
”DOMException
。并行运行此步骤:
- 给定 urlRecord、协议和条目设置对象,建立 WebSocket 连接。[拿来]
注意:如果建立 WebSocket 连接算法失败,则会触发失败 WebSocket 连接算法,该算法然后调用关闭 WebSocket 连接算法,该算法随后确定 WebSocket 连接已关闭,从而触发 close 事件,如下所述。
- 返回一个新的 WebSocket 对象,其 url 为 urlRecord。
请注意,连接的建立是“并行”运行的,并且规范进一步指出“...并行意味着这些步骤将与标准中的其他逻辑同时运行,一个接一个” (例如,该标准没有定义实现这一点的精确机制,无论是分时协作多任务、纤程、线程、进程,还是使用不同的超线程、核心、CPU、机器等。 ”
这意味着理论上可以在注册之前打开连接onOpen
,即使是onOpen(...)
构造函数调用之后的下一条语句。
然而......该标准在协议反馈下继续说明:
建立 WebSocket 连接后,用户代理必须将任务排队以运行以下步骤:
- 将属性的值更改
readyState
为OPEN
(1)。extensions
如果不是该值,请将属性的值更改为正在使用的扩展null
。[科进]protocol
如果不是该值,请将属性的值更改为正在使用的子协议null
。[科进]open
触发以该对象命名的事件WebSocket
。注意由于上述算法作为任务排队,因此正在建立的 WebSocket 连接和为 open 事件设置事件侦听器的脚本之间不存在竞争条件。
因此,在遵守 HTML 标准的浏览器或库中,如果注册的回调是在调用构造函数的执行块结束之前以及同一块中的任何后续语句之前注册的,则WebSocket.onOpen(...)
保证执行该回调释放事件循环(例如)。await
归档时间: |
|
查看次数: |
25659 次 |
最近记录: |