JavaScript中的Web Workers
Web Workers使我们能够编写多线程的JavaScript,而不会阻塞DOM。即使异步操作在某种程度上会阻塞DOM。另一方面,Web Workers帮助我们解决了这个问题,逃离了单线程环境,并提高了网页的性能。
使用方法:
- Web Workers存在于自己的文件中(不与用户界面进行交互)
- 函数是通过拷贝传递的
- 不允许使用全局变量
实现Web Workers
/* -----------------------------Index.JS--------------------------*/
// Check if web worker functionality is available for the browser
if(window.Worker){
// Creating new web worker using constructor
var worker = new Worker('worker.js');
var message = 'Hello';
// Sending the message using postMessage
worker.postMessage(message);
// On response
worker.onmessage = function(e) {
console.log(e.data);
};
}
/* -----------------------------Worker.JS--------------------------*/
// Waits for any activity from the page
self.onmessage = function(e) {
if(e.data !== undefined) {
// Do work
var total = e.data + ' World';
// Posting back to the page
self.postMessage(total)
}
}
// Terminate with: worker.terminate()
在上面的示例中,工作线程正在进行的工作是将收到的字符串与定义的字符串连接起来,并将其发送回到main.js文件,而不中断页面。
Output :’Hello World’
Web Workers没有访问以下内容的权限:
- 父对象
- 窗口对象
- 文档对象
- DOM
然而,它们可以访问以下内容:
- 位置对象
- 导航器对象
- XMLHttpRequest
- 应用程序缓存
- 产生其他 Web Workers (与父页面具有相同的源)
- 使用 importScripts() 导入外部脚本
常见用例:
- 需要复杂的计算计算时
- 在 HTML5 游戏中 (更高的帧率)
- 在任何包含 JavaScript 的网站中,以提高性能
真实世界示例:
以下程序被编写出来是为了展示我们的网页在有或没有Worker的情况下表现出的差异。
/* -----------------------------Index.JS--------------------------*/
const delay = 5000;
// Get element of without worker button
const noWorkerBtn = document.getElementById('worker--without');
// Add event listener to the button itself
noWorkerBtn.addEventListener('click', () => {
// Define the starting time
const start = performance.now();
// Do complex calculations
while (performance.now() - start < delay);
// Get the ending time
const end = performance.now();
// Calculate the difference in time
const resWithoutWorker = end - start;
// Log the result
console.log('No worker:', resWithoutWorker);
});
// Define a worker
const worker = new Worker('./worker.js');
// Get element of with worker button
const workerBtn = document.getElementById('worker--with');
// Add event listener to the button
workerBtn.addEventListener('click', () => {
// Send delay number
worker.postMessage(delay);
});
// On message from worker
worker.onmessage = e => {
// Log the result
console.log("With worker: ", e.data);
};
/* -----------------------------Worker.JS--------------------------*/
// On message received
this.onmessage = e => {
// Delay equals to data received
const delay = e.data;
// Define starting time
const start = performance.now();
// Do the complex calculation
while (performance.now() - start < delay);
// Get ending time
const end = performance.now();
// Calculate difference
const resWithWorker = end - start;
// Send result
this.postMessage(end - start);
};
示例:
Output: ‘No worker: 5000’
Output: ‘With worker: 5000’
这就是没有我们的工人代码时页面的表现方式:
- 动画会冻结,因为JavaScript正在阻塞DOM。
这是我们的工作代码在页面上的表现:
- 正如您所看到的,背景中的动画不会被中断,因为我们的工作线程为我们进行计算。通过这种方式,我们可以让DOM线程独立运行。