我有Web Worker。我希望用它定期发送网络请求。我特别想要的一件事就是即使主要的JS执行线程被阻止(例如通过window.alert)也要发出这些请求。我正在使用Chrome 38。
但是,当我尝试在worker中发出网络请求时,UI线程似乎阻止了请求。这是一个用来说明问题的人为例子:
base.js:
var worker = new Worker("/worker.js");
setTimeout(function() {
console.log("begin blocking");
var startDt = new Date();
var blockPeriod = 5000;
var a;
// Obviously we'd never actually do this, but this while loop
// is a convenient way to create the problem case (a blocked main
// thread).
while ((new Date() - startDt) < blockPeriod) {
a = 0;
}
console.log("stop blocking");
}, 3000);
worker.js:
var requestInterval = 1000;
var sendRequest = function() {
console.log("Send request interval");
var request = new XMLHttpRequest();
request.open("GET", "/ping", true);
request.onload = function() {
if (request.status === 200){
console.log(request.responseText)
} else {
console.log(request.status)
}
};
request.onerror = function() {
console.log("error")
};
request.send();
setTimeout(sendRequest, requestInterval);
}
sendRequest();
我看到的结果是我们看到成功的HTTP请求三秒钟,直到阻止开始。此时,在阻塞结束之前我们没有看到任何记录到控制台的内容,此时我们看到五个“发送请求间隔”,然后是5个响应日志,如下所示:
Send request interval
{"pong": true}
Send request interval
{"pong": true}
Send request interval
{"pong": true}
Send request interval
{"pong": true}
begin blocking
stop blocking
5x Send request interval
5x {"pong": true}
Send request interval
{"pong": true}
我还在服务器日志中看到在该阻塞时间内没有发出请求,然后在阻塞期结束时大致同时收到这五个请求。
鉴于“发送请求间隔”连续五次出现,工作人员显然继续执行:如果不是,则不会通过排队进行下一次迭代。我还发现,如果我通过触发window.alert而不是循环旋转来阻止,我会以1秒为间隔从sendRequest
的开头获取日志消息,然后获取响应处理程序日志消息一旦我停止阻止就会大批量。
在Firefox中,后台线程在这种情况下似乎完全停止(我在阻塞期间没有得到同一批五个请求排队)。但是,在这种情况下我只针对Chrome(我最终想要使用甚至不能在Firefox Workers中使用的WebSockets),所以我对此并不感兴趣。
所有这些都加在一起,这让我相信Web Workers中有一些活动被生成线程阻塞,有些活动没有(我最初看到了与WebSockets相同的行为)。具体来说,我想知道(如果有人知道):
答案 0 :(得分:5)
你的观察是正确的。当UI线程被阻止时,不会调度网络调用。
更糟糕的是,Chrome拥有最佳行为。当UI线程被阻止时,工作者发出XHR请求:
new XMLHttpRequest()
阻止,直到UI线程解除阻塞。xhr.open()
阻止,直到UI线程解除阻塞。虽然Chrome幸运不会导致工作线程停止并等待(即使它不会获得任何数据),但当您尝试发出XHR请求时,Firefox和IE将导致工作线程在UI线程上等待
没有办法解决这个问题;您会感谢浏览器代表您提出请求。我没有使用WebSockets进行任何测试,但即使UI线程被阻止,他们也可能传递事件。在最坏的情况下,收到的消息将排队,直到UI线程解除阻塞。
答案 1 :(得分:2)
如果有人偶然发现这种情况,这种行为被确认为一个错误(对于&#34的松散定义;&#34;因为&#34;它的行为不应该像#34;),在Blink中,截至2015年2月:
答案 2 :(得分:1)
我遇到了一个同样的问题,一个Web Worker执行一种保持活动状态:它会定期ping服务器,以通知该页面仍然有效。我也在工作程序中使用console.log,但是我确定这不是原因。
经过一些调查,我可以说问题可以解决两种不同的情况:
为解决此问题,我正在考虑在开始任何长时间的操作之前向服务器发送特殊的ping,以通知他在操作完成之前不会收到我的任何东西。
在我的情况下,此问题是由于ASP.NET会话状态锁定引起的:ASP.NET管道不会并发处理属于同一会话的请求,而是将它们排队并按顺序执行。这是详细的链接:http://tech-journals.com/jonow/2011/10/22/the-downsides-of-asp-net-session-state。
将控制器的会话状态标记为ReadOnly将解决此问题,而在Web.config中完全禁用会话状态(