Web Workers的强大之处- JavaScript中的多线程

Web Workers的强大之处- JavaScript中的多线程

Web Workers 是一个浏览器API,允许JavaScript在一个单独的线程中并行执行任务。它使主线程能够继续运行而不被阻塞,从而保持用户界面的响应性。Web Worker在一个独立的全局上下文中运行,这意味着它有自己的JavaScript引擎实例,因此不能直接访问主线程的变量或函数。相反,Web Workers使用消息传递系统与主线程进行通信。

创建Web Worker: 要创建Web Worker,我们可以使用Worker构造函数。Worker构造函数以URL作为参数,该URL是worker脚本文件的路径。然而,由于我们希望将worker代码包含在HTML文件中,我们可以使用一个blob来创建worker代码。

语法:

const worker = new Worker('worker.js');

与Web Workers通信: 创建了Web Worker后,我们可以使用postMessage()方法和onmessage事件处理程序在主线程和工作线程之间发送和接收消息。
以下代码片段将一条消息从主线程发送给Web Worker:

// Create a new web worker
const myWorker = new Worker("worker.js");

// Send a message to the worker
myWorker.postMessage("Hello, worker!");

在这段代码片段中,我们创建了一个新的Web Worker,并使用postMessage()方法向其发送消息。为了接收来自Web Worker的消息,我们需要为 onmessage 事件添加一个事件监听器。以下是接收来自Web Worker消息的代码片段:

// Create a new web worker
const myWorker = new Worker("worker.js");

// Receive a message from the worker
myWorker.onmessage = function (event) {
    console.log(event.data);
};

在这段代码中,我们创建了一个新的网页工作者,并为onmessage事件添加了一个事件监听器。当网页工作者向主线程发送消息时,onmessage事件处理程序被调用,并将消息记录到控制台。

示例1:(结合上述所有代码片段): 计算一个数字的阶乘,比如10。我们可以使用Web Worker在一个单独的线程中执行这个计算,像这样:

HTML

<!DOCTYPE html> 
<html> 
  
<head> 
    <title>Web Workers Example</title> 
    <style> 
        body { 
            text-align: center; 
        } 
  
        h1 { 
            color: green; 
        } 
    </style> 
</head> 
  
<body> 
    <h1>GeeksforGeeks</h1> 
  
    <h2>Web Workers Example</h2> 
  
    <p> 
        Calculate the factorial of 10 using a  
        web worker to prevent blocking the UI  
        thread. 
    </p> 
  
    <div id="result"></div> 
  
    <script> 
        const worker = new Worker(URL.createObjectURL(new Blob([ 
            ` 
            // Worker script 
            const factorial = (n) => { 
                if (n == 0 || n == 1) { 
                    return 1n; 
                } else { 
                    return BigInt(n) * factorial(BigInt(n) - 1n); 
                } 
            }; 
                       
            self.onmessage = (event) => { 
                const result = factorial(event.data); 
                self.postMessage(result.toString()); 
            };` 
        ], { type: "text/javascript" }))); 
  
        worker.postMessage(10n); 
  
        worker.onmessage = (event) => { 
            const result = event.data; 
            document.getElementById("result").innerHTML 
                = `Factorial of 10 is ${result}`; 
        }; 
    </script> 
</body> 
  
</html> 

输出:

Web Workers的强大之处- JavaScript中的多线程

说明: 在这个例子中,我们通过实例化Worker类并使用包含worker代码的新Blob对象的URL来创建一个新的Web Worker。该worker的代码在一个匿名函数中定义,使用递归函数计算一个数的阶乘。worker使用self.onmessage事件监听从主线程发送的消息,计算输入数的阶乘,并使用self.postMessage方法将结果发送回主线程。

在主线程中,我们创建一个新的worker实例,并发送一个包含数字10n(n后缀表示这是一个BigInt值)的消息给它。一旦worker计算完成阶乘,它就会使用postMessage方法将结果发送回主线程。主线程在onmessage事件中接收到结果,并使用计算后的值更新结果div元素的HTML内容。

例子2: 这个例子打印出小于等于n的素数。该例子允许用户输入一个数字,然后使用web worker计算出小于等于该数字的所有素数。worker脚本检查每个数字是否为素数,并将所有素数的数组返回给主线程以在结果段落中显示。

HTML

<!DOCTYPE html> 
<html> 
  
<head> 
    <meta charset="UTF-8"> 
    <title>Web Worker Example</title> 
    <style> 
        body { 
            text-align: center; 
        } 
  
        h1 { 
            color: green; 
        } 
    </style> 
</head> 
  
<body> 
    <h1>GeeksforGeeks</h1> 
  
    <h2>Web Worker Example</h2> 
  
    <p> 
        This example shows how to use a web 
        worker to perform a long-running task 
        without blocking the main thread. 
    </p> 
  
    <p> 
        Enter a number below to find all prime 
        numbers up to that number. 
    </p> 
  
    <input type="number" id="num" min="1"> 
    <button onclick="startWorker()">Start</button> 
    <button onclick="stopWorker()">Stop</button> 
    <p id="result"></p> 
  
    <script> 
  
        // Create a new worker 
        let worker; 
  
        function startWorker() { 
            const num = document.getElementById("num").value; 
            if (num === "") { 
                alert("Please enter a number"); 
                return; 
            } 
  
            worker = new Worker("data:text/javascript;base64," 
                + btoa(workerScript)); 
  
            // Send message to worker 
            worker.postMessage(num); 
  
            // Listen for message from worker 
            worker.onmessage = function (event) { 
                document.getElementById("result").innerHTML = 
                    event.data.join(", "); 
            }; 
        } 
  
        function stopWorker() { 
            worker.terminate(); 
        } 
  
        // The script to be executed in the worker 
        const workerScript = ` 
            function isPrime(num) { 
                if (num < 2) { 
                    return false; 
                } 
               
                for (let i = 2; i < num; i++) { 
                    if (num % i === 0) { 
                        return false; 
                    } 
                } 
               
                return true; 
            } 
               
            onmessage = function(event) { 
                const num = parseInt(event.data); 
                const primes = []; 
               
                for (let i = 2; i <= num; i++) { 
                    if (isPrime(i)) { 
                        primes.push(i); 
                    } 
                } 
               
                postMessage(primes); 
            };`; 
    </script> 
</body> 
  
</html> 

输出:

Web Workers的强大之处- JavaScript中的多线程

Web workers的好处:

  • 在JavaScript中实现多线程
  • 通过在单独的线程中执行计算密集型任务来提高性能
  • 避免阻塞主线程,使用户体验更加响应

使用web workers的缺点:

  • 内存消耗增加
  • 主线程和worker之间的通信开销
  • 总体而言,web workers是JavaScript语言的一项有价值的增加,在解决阻塞主线程问题方面提供了解决方案。通过利用web workers,开发人员可以创建更快、响应更快的Web应用程序,从而改善受众的用户体验。

结论: 重要的一点要注意的是,使用web workers也可能有缺点。由于workers是独立的执行线程,它们可能会增加应用程序的内存消耗。此外,主线程和workers之间的通信会引入开销,使应用程序变慢。因此,必须仔细考虑使用web workers,并且只在必要时使用它们。总之,Web workers是一个强大的工具,可以实现JavaScript的多线程,使我们能够执行计算密集型任务而不阻塞主线程。通过利用web workers,我们可以显著提高Web应用程序的性能,创造更快、更响应的用户体验。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程