JavaScript是一种单线程语言,这意味着一次只能运行一个脚本。使用UI DOM并执行复杂的计算有时会导致应用程序缓慢运行或显得无反应的问题。
通常会混淆多线程和异步编程。由于异步任务是非阻滞的,并且可以同时执行,因此它们不依赖彼此。但是他们仍在使用单线程。
要使用多线程进行复杂的计算,这是Web Worker的概念。
本文使用的示例可以在以下link
中找到什么是网络工作者?
Web Worker是一个JavaScript进程,在后台运行,与网页的主线程分开。主线程是默认的JavaScript线程,我们称之为单个线程。
这负责一次将网页的所有JavaScript作为一行。因此,基本上,Web工作人员允许您彼此并行执行JavaScript的多个线程。为了避免进行所有繁重举重的主线程,可以创建和用于卸载昂贵的工作,因此主线程可以继续执行其他代码。要注意,可以面对一个缺点:可以使用网络工作人员来操纵DOM,只有主线程才能访问DOM并操纵它。
我们如何以及在哪里可以使用Web Worker并与主线程相称?
现在,正如我们知道网络工作者是什么,我们将看到如何和何处实现和使用。
我们有两个按钮:一个用于进行总和,另一个用于更改背景颜色。如果我们尝试计算总和并立即尝试更改背景颜色,则可能会导致主线程的块。正如我们在下面看到的那样,对于循环是一个昂贵的操作,我们只有一个正在处理总和计算的线程,因此它将阻止其他操作直到使用for循环完成。
const sumButton = document.getElementById("sumButton");
const backgroundButton = document.getElementById("backgroundButton");
sumButton.addEventListener("click", function () {
let sum = 0;
for (let index = 0; index < 10000000000000; index++) {
sum += index;
}
alert(`total sum ${sum}`);
});
backgroundButton.addEventListener("click", function () {
if (document.getElementById("container").style.backgroundColor != "blue") {
document.getElementById("container").style.backgroundColor = "blue";
} else {
document.getElementById("container").style.backgroundColor = "green";
}
});
为了避免此问题,我们可以创建网络工人,这些工作人员将以Web Worker和主线程将相互通信以传递数据的方式并行工作。为了使用它,我们可以创建一个实例。
我们将为Web Worker定义构造函数如下:
const worker = new Worker("worker.js");
如图中所示,工人构造函数采用了工作脚本的路径,因此,首先,我们需要创建一个文件,在其中定义了工人将要做的工作。创建后,我们需要了解如何将数据传递给主脚本和工人。我们将数据传递给工人的方式是使用方法postmessage()。从本质上讲,帖子消息从一个脚本中提出了一个事件,其他脚本可以听。我们可以通过以下方式在Worker脚本上设置事件侦听器,以收听新的文章消息:
self.onmessage= function(message){}
在这里,我们正在创建一个事件处理程序,因此每当收到新的帖子消息时,工人都需要做某事。
现在,为了解决我们之前提到的有关执行重循环以计算总和的问题,我们将将代码移至Worker脚本:
self.onmessage = function (message) {
let sum = 0;
for (let index = 0; index < 10000000000000; index++) {
sum += index;
}
this.postMessage(sum);
};
这样,工人将同时完成背景过程中的所有总和,以避免阻止主线程。这里的问题是工人将做总和,但实际上并没有在完成主线程时告诉主线程。因此,为此,我们将使用Postmessage()。工人将总和通过后线程发送到主线程(),主脚本将捕获消息:
onmessage = function (message) {
let sum = 0;
for (let index = 0; index < 10000000000000; index++) {
sum += index;
}
this.postMessage(sum);
};
worker.onmessage = function (event) {
alert(`Total Sum: ${event.data}` );
};
主线程脚本看起来像这样:
const worker = new Worker("worker.js");
const sumButton = document.getElementById("sumButton");
const backgroundButton = document.getElementById("backgroundButton");
sumButton.addEventListener("click", function () {
worker.postMessage("Sum Button clicked");
});
worker.onmessage = function (event) {
alert(`Total Sum: ${event.data}` );
};
backgroundButton.addEventListener("click", function () {
if (document.getElementById("container").style.backgroundColor != "blue") {
document.getElementById("container").style.backgroundColor = "blue";
} else {
document.getElementById("container").style.backgroundColor = "green";
}
});
得出结论,尽管JavaScript是一个线程,但我们仍然可以使用网络工人同时和有效地运行我们的任务而不会影响主线程。
参考书目
Multithreading in Javascript Using Worker Threads
Multithreading Javascript