在发送XHR时,Web工作人员不是真正的并发?
问题描述:
这个问题出现在一个巨大而复杂的应用程序中,但它可以在一个简单的用例中重现:如果主浏览器线程繁忙, 由web worker发送的XHR将阻塞,直到主浏览器线程空闲,就好像工作人员是一个正常的功能,挂起0ms超时, 等待其主线程启动。实际上并没有发生什么:正在发生并发,我们可以从日志条目的时间戳 中看出,但似乎只有在主Javascript线程是空闲时才能完成XMLHttpRequest的实际发送。首先,我们认为这种行为仅限于Internet Explorer,但实际上它只是以这种方式出现,因为IE在我们特定的 用例中慢得多,因此主浏览器线程保持更长时间的忙碌状态。这种非并发行为实际上出现在我尝试过的所有浏览器中(IE, Chrome,Firefox)。浏览器的行为并不完全相同:有时他们在open()调用上阻塞,有时他们在send()上阻塞,有时他们声称send()及时完成,但使用HTTP调试器如Fiddler显示数据实际上并未发送到 服务器,直到主浏览器线程完成其长时间运行的任务。在发送XHR时,Web工作人员不是真正的并发?
所以我希望有人能告诉我为什么这样,以及是否有任何方法让网络工作者以恰当的并发方式发送XHR。顺便说一句,我 已经知道,总体问题的关键是主要的Javascript线程是多么繁忙,所以请不要告诉我解决这个问题;我们是也在 上工作,但是长期运行的任务是在客户的应用程序中对基于JS的非常复杂的用户界面进行回流,所以我们在这里可以做的事情仅限于 。
这个摄制情况说明了什么问题:
<html>
<body>
<div id="test"></div>
<script>
worker = new Worker('worker.js');
// Wait for 2 seconds to be as sure as we can be that it has downloaded and installed the worker code
setTimeout(proceed, 2000);
function proceed() {
worker.postMessage("");
console.log("Message sent to worker: " + new Date().getTime());
// Now tie up the JS thread
setTimeout(function() {
console.log("Started crazy pointless loop: " + new Date().getTime());
for (var i = 0; i < 500000; i++) {
var j = i/17,
k = j * j,
l = k/123;
document.getElementById("test").innerHTML = "l = " + l;
}
console.log("Finished crazy pointless loop: " + new Date().getTime());
}, 0);
}
</script>
</body>
</html>
和worker.js文件:
addEventListener('message', function(e) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState < 4) return;
console.log("Response received: " + new Date().getTime());
}
console.log("Ready to open XHR: " + new Date().getTime());
xhr.open("GET", "dummy.html?nocache=" + new Date().getTime(), true);
console.log("XHR opened: " + new Date().getTime());
xhr.send();
console.log("XHR sent: " + new Date().getTime());
}, false);
答
你会更好,从工人同步发送XHR因为你已经在一个单独的线程中运行:
addEventListener('message', function(e) {
var xhr = new XMLHttpRequest();
console.log("Ready to open XHR: " + new Date().getTime());
xhr.open("GET", "dummy.html?nocache=" + new Date().getTime(), false); // false makes it synchronous
console.log("XHR opened: " + new Date().getTime());
xhr.send();
console.log("Response received: " + new Date().getTime());
}, false);
我没有任何数据支持此,所以这不是一个答案。但是我强烈怀疑所有浏览器都使用主线程来限制给定域的并发连接数。对于任何给定的域,HTTP 1.1指定不超过2个。尽管大多数浏览器并不尊重极限,但它们都具有我期望通过主线程执行的上限。有关更多信息,请参阅http://*.com/questions/985431/max-parallel-http-connections-in-a-browser。 –