如果我在网络工作者中做了几秒钟的计算,我可以期望UI不会因为它而口吃吗?包括手机?如果没有,我该怎么办呢?工作量很容易分成更小的块,但大约一半的站点在计算完成之前不起作用。
答案 0 :(得分:2)
...我可以期待用户界面不会因为它而口吃吗?
很大程度上,是的,您可以在浏览器和设备的能力范围内。毕竟,这是网络工作者的 raison d'être:将长时间运行的进程从UI线程移开,以便UI可以保持响应。没有任何保证,但是......根据实际情况:我已经完成了测试,其中工作人员在主UI更新时忙于循环30秒以上,并且它在桌面,Android和iOS上运行良好。
这样的测试并不困难:
实时代码段(因为我正在创建工作人员,可能无法在所有设备上运行):
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>