1、Web Worker简介
JavaScript 是一种单线程语言,这意味着在一个页面中,所有的 JavaScript 代码都在同一个线程中运行。在单线程模型中,所有任务都是按顺序执行的,如果某个任务需要花费较长时间才能完成,它将阻塞其他任务的执行。HTML5 引入了 Web Workers技术,允许在浏览器中创建多个 JavaScript 线程,以便在后台执行计算密集型任务,从而避免阻塞主线程。Web Worker 是一个独立的 JavaScript 程序,它运行在与主线程不同的上下文中,并且与主线程是完全独立的, 可以运行长时间运算、处理大量数据或与服务器通信等任务,而不会阻塞页面的用户界面。
下面是 Web Worker 的几个优点:
- 提高页面性能:Web Worker 可以在后台线程中执行一些计算密集型或者耗时的操作,如数据处理、图像处理等,而不会占用主线程,从而避免了页面卡顿或者卡死的情况,提高了页面的性能和响应速度。
- 可以处理大规模数据:Web Worker 可以处理大规模的数据,因为它们在单独的线程中运行,不会影响主线程的运行,可以更高效地处理大规模的数据,提高了代码的效率和可扩展性。
- 可以使代码更加模块化:使用 Web Worker,可以将代码分割成多个模块,分别运行在不同的线程中,从而使得代码更加模块化,可维护性和可读性更强。
- 支持多线程:Web Worker 支持多线程,因此可以利用多核处理器的优势,提高代码的运行效率。
2、Web Worker的创建和使用
2.1 创建 Worker
在主线程中使用new Worker()构造函数来创建一个新的Worker对象,例如:
const worker =newWorker('worker.js');
这里的
worker.js
是一个独立的 JavaScript 文件,它将作为 Worker 的入口点。当创建 Worker 实例时,浏览器会将
worker.js
文件加载到一个独立的执行环境中,并开始运行它。
2.2 发送消息
以使用Worker对象的postMessage()方法向工作线程(worker.js)发送消息。例如:
worker.postMessage('Hello, worker!');
2.3 在工作线程(worker.js)中处理消息
在工作线程worker.js中,您可以使用onmessage事件监听器来接收来自主线程的消息,并使用postMessage()方法向主线程发送消息。例如:
onmessage=function(e){
console.log('Message received from main thread:', e.data);postMessage('Hello, main thread!');}
这里的onmessage函数将在主线程发送消息时被调用,并将“Hello, main thread!”发送回主线程。
2.4 监听消息事件
在主线程中,可以使用onmessage事件监听器来接收来自工作线程的消息。例如:
Worker.onmessage=function(e){
console.log('Message received from worker:', e.data);}
2.5 Web Worker 的关闭
当你使用 Web Worker 时,它会占用一定的系统资源,如内存等。如果你创建了太多的 Worker,或者没有关闭它们,会导致系统资源的消耗,从而影响整个应用程序的性能。因此,为了避免资源泄漏和提高系统性能,我们应该在不再需要使用 Worker 的时候及时关闭它们。可以使用 Worker.terminate() 方法来关闭一个 Web Worker。
// 关闭Web Worker
worker.terminate();
2.6 worker.js文件加载引用
- 使用在html中引用 worker.js文件
<!-- 将worker.js文件包含在HTML中 --><script src="worker.js"></script>
- 在javascript代码中直接引用
<!-- worker.js和主程序在同一文件夹下 -->const worker =newWorker('worker.js');<!-- worker.js和主程序不在同一文件夹下 -->const worker =newWorker('../resource/fundids/js/worker_diff.js');3
- worker.js中加载其他JavaScript代码 在Web Worker中,您不能直接访问页面中的DOM元素和JavaScript对象。如果您的Web Worker需要访问其他JavaScript代码,您可以使用importScripts()方法加载它们。importScripts()方法可以接受一个或多个参数,这些参数是需要加载的JavaScript文件的URL。在加载这些文件时,它们将立即被执行,并且在Web Worker的全局作用域中定义的所有变量和函数都将在Web Worker中可用。以下是一个示例,演示了如何在Web Worker中使用importScripts()方法加载其他JavaScript代码:
// 在这里可以使用在file1.js和file2.js中定义的变量和函数importScripts("file1.js","file2.js");
2.5 使用Web Worker实例
<!DOCTYPEhtml><html><head><title>Web Worker 斐波那契数列</title><script>// 创建一个新的 Web Worker,指定 worker.js 文件作为代码文件const worker =newWorker('worker.js');// 向 Web Worker 发送一个消息
worker.postMessage(100);// 监听 Web Worker 返回的结果
worker.onmessage=function(event){
console.log('斐波那契数列:', event.data);var resultElement = document.getElementById("result");
resultElement.innerHTML +="<span>"+event.data+"</span>";};</script></head><body><h1>Web Worker Example</h1><divid="result"></div></body></html>
在 worker.js 文件中,我们可以实现计算斐波那契数列的代码:
// 监听来自主线程的消息onmessage=function(event){const n = event.data;var result =fibonacciArray(n);// 将结果发送回主线程postMessage(result);};// 计算斐波那契数列functionfibonacciArray(n){var fib =[1,1];// 前两个数字是1for(var i =2; i < n; i++){
fib[i]= fib[i-1]+ fib[i-2];// 计算下一个数字并添加到数组中}return fib;}
在这个示例中,我们使用了一个 Web Worker 来计算斐波那契数列。当主线程向 Web Worker 发送一个消息时,Web Worker 开始计算斐波那契数列,并将结果发送回主线程。由于计算斐波那契数列可能需要一些时间,因此使用 Web Worker 可以避免阻塞主线程,从而提高页面性能和用户体验。
3、web worker缺陷
- 无法直接访问 DOM:由于 Web Worker 运行在独立的线程中,不能直接访问主线程中的 DOM,因此需要使用特殊的方式进行通信,如 postMessage() 方法。
- 无法访问主线程中的 JavaScript 对象:Web Worker 独立运行在一个线程中,无法直接访问主线程中的 JavaScript 对象,需要使用序列化和反序列化等技术进行数据传递。
- 无法加载本地文件:Web Worker 只能通过网络加载 JavaScript 文件,无法直接加载本地文件。
- 无法执行同步操作:Web Worker 无法执行同步操作,如读取文件或等待用户的输入等,因为同步操作会阻塞 Web Worker 的线程。
- 不支持所有浏览器:Web Worker 不是所有浏览器都支持,尤其是一些旧版的浏览器可能不支持 Web Worker。
if(typeof(Worker)!=="undefined"){// 支持webworker}
4、Web Worker与后端传输数据
Web Worker 不能直接访问主线程中的 DOM。这意味着 Web Worker 不能直接操作页面的 HTML 元素或修改浏览器的 URL。但是,Web Worker 可以使用 XMLHTTPRequest 和 Fetch API 等技术从服务器获取数据,并通过消息传递机制将数据发送给主线程。
4.1 使用XMLHttpRequest
// 监听从主线程发送来的消息onmessage=function(event){var data = event.data;var newData =[];for(var i =0; i < data.length; i++){_add(data[i]);};};function_add(d,flag){var num1 = d.num1;var num2 = d.num2;var id = d.id;// 创建 XMLHttpRequest 对象var xhr =newXMLHttpRequest();// 监听请求状态变化事件
xhr.onreadystatechange=function(){if(xhr.readyState ==4&& xhr.status ==200){// 请求成功
result ={"id":id,"num1":num1,"num2":num2,"result":xhr.responseText};postMessage(result);}};// 发送 AJAX 请求
xhr.open("POST","/test/WebWorkers/add_ajax.tsl",true);// 打开请求连接// xhr.setRequestHeader("Content-type", "application/json"); // 设置请求头
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');// var data = {dowhat:'add', num1:num1, num2:num2}; // 定义要发送的数据并转换为 JSON 字符串// xhr.send(JSON.stringify(data)); // 发送数据var data =newURLSearchParams();
data.append("num1",num1);
data.append("num2",num2);
xhr.send(data);// 发送数据}
4.2 Fetch API
function_add2(d){var num1 = d.num1;var num2 = d.num2;var id = d.id;//var data = new URLSearchParams();var formData =newFormData();
formData.append("num1",num1);
formData.append("num2",num2);fetch("/test/WebWorkers/add_ajax.tsl",{method:'POST',body: formData
}).then(response=> response.json()).then(data=>{
result ={"id":id,"num1":num1,"num2":num2,"result":data};postMessage(result);}).catch(error=> console.error(error))}
FormData是一种用于处理表单数据的JavaScript API,它可以通过XMLHttpRequest或fetch()方法发送表单数据到后端服务器。FormData对象包含一个键值对列表,可以用于构建表单数据。可以使用FormData对象的append()方法向FormData对象添加键值对。
如上使用了FormData()以表单的形式提交数据,后端即可直接Q(“name”)获取数据,如果提交不同格式的数据,如json串等,当前后端获取前端参数的方法可能不支持。
6、应用场景
Web Worker 的一些应用场景:
- 图像处理:在 Web 应用程序中,经常需要对图片进行处理、缩放、剪裁等操作。这些操作可能会消耗大量的 CPU 时间和内存资源,导致页面变卡。使用 Web Worker 可以将这些计算密集型任务放到后台线程中执行,避免阻塞主线程。
- 数据计算:对于大规模的数据集,需要进行复杂的计算和数据分析,例如数据挖掘、机器学习、人工智能等。这些任务需要大量的计算资源和时间,使用 Web Worker 可以将计算任务分散到多个线程中,加快计算速度。
- 后台请求:在 Web 应用程序中,可能需要进行一些后台请求和数据处理,例如与服务器进行交互、读写文件等。使用 Web Worker 可以将这些任务放到后台线程中执行,避免阻塞主线程,提高应用程序的性能和响应速度。
- 多媒体处理:在 Web 应用程序中,经常需要对音频、视频等多媒体资源进行处理和转码,这些任务需要大量的计算资源和时间。使用 Web Worker 可以将这些任务放到后台线程中执行,避免阻塞主线程。
需要注意的是,Web Worker 并不是适用于所有场景的解决方案。对于一些简单的任务,使用 Web Worker 可能会增加代码复杂度,并且可能会带来额外的开销和性能问题。因此,在应用 Web Worker 时需要根据具体情况进行评估和选择。
版权归原作者 恶龙没有咆哮 所有, 如有侵权,请联系我们删除。