但是,当我尝试在工作中发出网络请求时,请求似乎被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工作中使用的WebSockets),所以我对此并不感兴趣.
所有这些都加在一起,这导致我相信Web Worker中有一些类被活动的线程阻塞,有些不是(我最初看到与WebSockets相同的行为).具体来说,我想知道(如果有人知道):
> Chrome中的主线程阻止了什么工作者活动?
有没有办法解决这个问题?我非常希望能够在Worker中建立一个WebSocket连接,然后继续执行PING / PONG,即使某些事情(如警报/确认)也阻止了主线程.
这是一切废话,我只是在做一些愚蠢的事情吗?
解决方法
更糟糕的是,Chrome具有最好的行为.当UI线程被阻止时,工作者进行XHR请求:
> Chrome:所有请求都排队等待.在UI线程解除阻塞之前,浏览器实际上不会发出请求.在正面方面,工作线程仍然可以自由运行.
> Firefox:新的XMLHttpRequest()阻塞,直到UI线程解除阻塞.
> IE:xhr.open()阻塞,直到UI线程解除阻塞.
虽然Chrome幸运的是不会导致一个工作线程停止和等待(即使它不会得到任何数据),Firefox和IE会导致一个工作线程等待UI线程,当你尝试做一个XHR请求.
没有办法解决这个问题您对浏览器的支持,代表您提出请求.我没有使用WebSockets进行任何测试,但即使UI线程被阻止,他们也可能会传送事件.在最坏的情况下,接收到的消息将排队,直到UI线程解除阻塞.