这是一个简单的剪辑来执行Ajax请求
var req = new XMLHttpRequest();
req.open('GET', 'http://www.mozilla.org/', true);
req.send(null); // First - send the request
// Then bind for the "result"
req.onreadystatechange = function (e) {
if (req.readyState == 4 && req.status == 200) {
// ...
}
};
我在这做什么:
如果您认为此代码为多线程 - 很明显您可以在请求完成后绑定到onreadystatechage
(由于调度),并且永远不会调用它。
但是在基于反应堆的代码中,这将始终按预期工作,因为反应堆将不会运行,直到我的所有代码完成该迭代的运行。
浏览器的情况如何?这是在某处记录的吗?
忽略Ajax请求很慢的事实,这在实践中可能永远不会发生。我只是将它作为异步示例(如果ajax对你来说太慢,请考虑websocket)。
答案 0 :(得分:2)
理论上没有,事件处理程序的触发应该发生在事件队列上,因此必须在当前时间片完成后的时间片中发生,这意味着{{1在处理任何事件之前发生。请参阅javascript - event driven and concurrency issues?以了解JavaScript的并发模型(至少在浏览器中)。
实际上,Firefox曾经(可能还有)一个错误,其中特别是req.onreadystatechange = ...
事件与使用onreadystatechange
对象发送请求的帧的事件队列同时触发。我养成了让XMLHttpRequest
处理程序执行onreadystatechange
的习惯,以确保我在Firefox上没有令人讨厌的交错。
如果你在setTimeout(0, ...)
中使用XMLHttpRequest
对象跨帧,也可以使用new otherWindow.XMLHttpRequest(...)
对象,因为这样可以在当前时间片之前的另一帧的事件队列中处理响应(在此帧的事件中)队列)完成。
答案 1 :(得分:2)
从这个意义上讲,JavaScript并不是多线程的。在你说完.send(null)之后,你将完成执行当前的代码块,其中包括onreadystatechange,然后才会触发事件。对于事件触发,您的代码不会在这两个句子之间被中断 - 事件将被添加到事件队列中(如果愿意,将被缓冲),并且当有时间时,事件将触发,调用与之关联的所有处理程序。它应该调用在创建XMLHttpRequest对象和触发事件之间添加的处理程序。
至少,这是我对这个问题的解释。有关详细信息,请访问dev.opera上的Timing and synchronization in Javascript。
答案 2 :(得分:1)
如果您在请求触发后订阅它,是否有可能“错过”JS中的异步事件?
不,这是不可能的 - if 在事件发生之前绑定处理程序。
事件发生无论如何。如果是这样,将调用此时注册的所有处理程序。
答案 3 :(得分:1)
理论上它是可能的。
为避免将req.onreadystatechange = ...
放在req.send(null);
之前。