У меня есть веб-рабочий. Я хочу сделать с ней периодические сетевые запросы. Одна вещь, которую я особенно хочу, это сделать эти запросы, даже если основной поток выполнения JS заблокирован (например, с помощью window.alert). Я использую Chrome 38.
Однако, когда я пытаюсь выполнить сетевые запросы у рабочего, запросы, как представляется, блокируются потоком пользовательского интерфейса. Вот надуманный пример, иллюстрирующий проблему:
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 вместо вращения в цикле, я получаю сообщения журнала с начала sendRequest
с интервалом в 1 секунду, а затем получаю сообщения журнала обработчика ответа в большом пакет, как только я остановлю блокировку.
В Firefox фоновый поток, кажется, полностью останавливается в этом случае (я не получаю ту же самую партию из пяти запросов, стоящих в очереди в течение заблокированного периода). Тем не менее, я ориентируюсь только на Chrome в этом случае (и в конечном итоге хочу использовать WebSockets, которые даже не работают в Firefox Workers), поэтому меня это не интересует.
Все добавленное вместе, это заставляет меня поверить, что в Web Workers есть некоторые классы активности, которые блокируются нерестовым потоком, а некоторые из них (я изначально видел такое же поведение с WebSockets). Конкретно, я хотел бы знать (если кто-то знает):
- Какая активность рабочего заблокирована основным потоком в Chrome?
- Есть ли способ обойти это? Мне очень хотелось бы иметь возможность установить соединение WebSocket у Рабочего, а затем продолжить PING/PONG взад и вперед, даже если что-то (например, предупреждение/подтверждение) блокирует основной поток.
- Это все глупости, и я просто делаю что-то глупое?