Имеет ли поток пользовательского интерфейса приоритет над веб-работниками?

Если я выполняю многосекундные вычисления в веб-воркере, могу ли я ожидать, что пользовательский интерфейс не будет заикаться из-за этого? В том числе мобильный? Если нет, что я могу с этим поделать? Рабочую нагрузку легко разделить на более мелкие части, но примерно половина сайта не работает, пока не будут выполнены эти вычисления.


person Filip Haglund    schedule 15.04.2018    source источник
comment
Это неподтвержденное свидетельство из 2012 года, кажется, говорит о том, что тогда поток пользовательского интерфейса забивался на большую нагрузку веб-работника веб-сайты-web-workers-or-cgi" title="как обрабатывать массивные вычисления на веб-сайтах веб-воркеров или cgi"> stackoverflow.com/questions/9758999/   -  person Filip Haglund    schedule 15.04.2018
comment
массивные и долгие вычисления немного субъективны. Как правило, нагрузка на веб-воркер не должна влиять на поток пользовательского интерфейса. Можете ли вы объяснить немного больше о том, что вы пытаетесь разгрузить в работника?   -  person Nisarg    schedule 15.04.2018


Ответы (1)


... могу ли я ожидать, что пользовательский интерфейс не будет заикаться из-за этого?

В основном да, можно, в пределах возможностей браузера и устройства. В конце концов, это смысл существования веб-воркеров: вывести длительные процессы из потока пользовательского интерфейса, чтобы пользовательский интерфейс мог оставаться отзывчивым. Гарантий нет, но... Эмпирически: я проводил тесты, в которых рабочий цикл зацикливался на 30+ секунд, пока обновлялся основной пользовательский интерфейс, и он отлично работал на настольных компьютерах, Android и iOS.

Такие испытания не сложны:

Прямая трансляция на plnkr

Живой фрагмент (может работать не на всех устройствах из-за того, как я создаю работника):

const chars = "|/-\\".split("");
let charindex = -1;
const spinner = document.getElementById("spinner");
setInterval(() => {
    charindex = (charindex + 1) % chars.length;
    spinner.innerHTML = chars[charindex];
}, 50);
function log(msg) {
    const p = document.createElement("pre");
    p.appendChild(document.createTextNode(msg));
    document.body.appendChild(p);
}
function main() {
    const url = URL.createObjectURL(
      new Blob([
        document.getElementById("worker").textContent
      ], {type: "text/javascript"})
    );
    const w = new Worker(url);
    w.onmessage = function(event) {
        if (event.data === "ready") {
            w.postMessage("start");
        } else {
            log(event.data);
        }
    };
}
main();
<div id="spinner"></div>
<script id="worker" type="worker">
this.addEventListener("message", e => {
    if (e.data === "start") {
        let last = Date.now();
        const stop = last + 20000;
        let now;
        while ((now = Date.now()) < stop) {
            if (now - last > 1000) {
                postMessage("tick");
                last = now;
            }
        }
    }
});
postMessage("ready");
</script>

worker.js:

this.addEventListener("message", e => {
    if (e.data === "start") {
        let last = Date.now();
        const stop = last + 30000;
        let now;
        while ((now = Date.now()) < stop) {
            if (now - last > 1000) {
                postMessage("tick");
                last = now;
            }
        }
    }
});
postMessage("ready");

host.html:

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Worker Host</title>
<style>
body {
    font-family: sans-serif;
}
</style>
</head>
<body>
<div id="spinner"></div>
<script>
const chars = "|/-\\".split("");
let charindex = -1;
const spinner = document.getElementById("spinner");
setInterval(() => {
    charindex = (charindex + 1) % chars.length;
    spinner.innerHTML = chars[charindex];
}, 50);
function log(msg) {
    const p = document.createElement("pre");
    p.appendChild(document.createTextNode(msg));
    document.body.appendChild(p);
}
function main() {
    const w = new Worker("worker.js");
    w.onmessage = function(event) {
        if (event.data === "ready") {
            w.postMessage("start");
        } else {
            log(event.data);
        }
    };
}
main();
</script>
</body>
</html>
person T.J. Crowder    schedule 15.04.2018
comment
Да, я нашел pmav.eu/stuff/javascript-webworkers и запустил его с 16+ потоки без слишком большой задержки пользовательского интерфейса на рабочем столе или на мобильном устройстве - person Filip Haglund; 15.04.2018