UI 线程是否优先于网络工作者?

Does the UI thread have priority over web workers?

如果我在 web worker 中进行几秒长的计算,我能期望 UI 不会因此而卡顿吗?包括手机?如果没有,我该怎么办?工作负载很容易分成更小的块,但大约一半的站点在计算完成之前无法工作。

...can I expect the UI to not stutter because of it?

在浏览器和设备的能力范围内,基本上可以。毕竟,这是 Web 工作者的 存在理由 :将长 运行 进程移出 UI 线程,因此 UI可以保持响应。没有任何保证,但是......根据经验:我已经完成了工作人员忙循环 30 秒以上的测试,而主要 UI 更新,它在桌面上工作得很好,Android,和 iOS.

这样的测试并不难:

Live on 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>