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

时间:2018-04-15 08:16:14

标签: javascript web-worker

如果我在网络工作者中做了几秒钟的计算,我可以期望UI不会因为它而口吃吗?包括手机?如果没有,我该怎么办呢?工作量很容易分成更小的块,但大约一半的站点在计算完成之前不起作用。

1 个答案:

答案 0 :(得分:2)

  

...我可以期待用户界面不会因为它而口吃吗?

很大程度上,是的,您可以在浏览器和设备的能力范围内。毕竟,这是网络工作者的 raison d'être:将长时间运行的进程从UI线程移开,以便UI可以保持响应。没有任何保证,但是......根据实际情况:我已经完成了测试,其中工作人员在主UI更新时忙于循环30秒以上,并且它在桌面,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>