一、Web Worker 介绍
JavaScript 是一种单线程语言,意味着它在一个时间点只能执行一个任务。尽管如此,一个进程可以包含多个线程,例如浏览器中的 Web Worker 提供了一种在后台线程中运行脚本的方式,从而避免主线程被阻塞。
1. Web Worker 的作用
Web Worker 是浏览器提供的一种多线程机制,允许开发者在后台线程中运行 JavaScript 脚本,主要用于以下场景:
- 复杂计算:处理大量数据或复杂算法,避免阻塞主线程。
- 后台任务:如文件处理、音频处理等。
- 实时更新:如 WebSocket 数据处理、实时图表更新等。
2. 浏览器中的线程模型
谷歌浏览器是一个多进程架构的浏览器,每个进程可以包含多个线程。以下是常见的线程类型及其作用:
| 线程类型 | 主要任务 |
|---|---|
| 主线程 | 页面渲染、用户交互、JavaScript 执行 |
| 渲染线程 | 样式计算、布局计算、绘制和合成 |
| 工作线程 | Web Worker、Service Worker 等后台任务 |
| 网络线程 | HTTP 请求、WebSocket 通信 |
| GPU 线程 | 硬件加速渲染、3D 绘制 |
| 定时器线程 | setTimeout、setInterval 等定时任务 |
| I/O 线程 | 文件读写、数据库操作 |
| 音频线程 | 音频播放、音频处理 |
3. Web Worker 的使用示例
以下是一个简单的 Web Worker 示例,用于在后台线程中计算大数的阶乘:
new Worker(js文件)
主线程代码 main.js
const worker = new Worker('worker.js');
worker.postMessage(10); // 向 Worker 发送数据
worker.onmessage = (event) => {
console.log(`阶乘结果: ${event.data}`);
};
worker.js
// 计算阶乘函数
function factorial(n) {
if (n === 0 || n === 1) return 1;
return n * factorial(n - 1);
}
// 接收主线程发送的数据
onmessage = (e) => {
const result = factorial(e.data); // 计算 e.data 的阶乘
postMessage(result); // 将结果发送回主线程
};
- worker 运行在另一个全局上下文中,不同于当前的window
- worker和主线程传递数据使用 postmessage,响应数据使用onmessage
- worker 内不能操作dom节点,不能使用windows的方法和属性
- worker 内部,worker 是有效的全局作用域,直接调用postmessage方法
4. 终止worker
worker.terminate()
5.错误处理
onerror =(meeage,filename,lineno)=>{
}
6.subworker
worker 能够生成更多的 worker
7.引入库和脚本 importScripts引入脚本
importScripts(); /* 什么都不引入 */
importScripts("foo.js"); /* 只引入 "foo.js" */
importScripts("foo.js", "bar.js"); /* 引入两个脚本 */
importScripts("//example.com/hello.js"); /* 你可以从其他来源导入脚本 */
8.共享worker
const myWorker = new SharedWorker("worker.js");
myWorker.port.postMessage([first.value, second.value]);
onconnect = (event)=>{
const port = e.event[0]
port.onmessage=(e)=>{
// e.data
}
}
- 与一个共享 worker 通信必须通过 port 对象与 worker 通信
- worker中使用onconnect处理函数来执行代码,
- 使用事件的 ports 属性来获取端口并存储在变量中。
- 为端口添加一个 onmessage 处理函数用来做运算并回传结果给主线程
- worker 有它自己的执行上下文,worker 并不受限于创建它的 document(或者父级 worker)的内容安全策略
9. 其他类型的worker
- ServiceWorkers 基本上是作为代理服务器,位于 web 应用程序、浏览器和网络(如果可用)之间。离线体验,拦截网络请求
- Audio Worklet 提供了在 worklet(轻量级的 web worker)上下文中直接完成脚本化音频处理的可能性
10.调试worker线程
f12 下 source / worker可见

11. worker中可用的函数和接口
- Navigator
- fetch
- Array Date Math String
- setTimeout setInterval
在一个 worker 中最主要的你不能做的事情就是直接影响父页面。包括操作父页面的节点以及使用页面中的对象
二、 常用 Web Worker 库
1. react-useworker
react-useworker 是一个 React Hook 库,用于简化 Web Worker 的使用。它允许开发者轻松地将耗时的计算任务移到后台线程中,从而提高应用的性能。
使用方法
- 安装库:
npm install react-useworker - 示例代码:
import useWorker from 'react-useworker'; const App = () => { const [workerFn, { kill }] = useWorker((num) => { const factorial = (n) => (n <= 1 ? 1 : n * factorial(n - 1)); return factorial(num); }); const handleCalculate = async () => { const result = await workerFn(10); console.log(`阶乘结果: ${result}`); }; return ( <div> <button onClick={handleCalculate}>计算阶乘</button> <button onClick={kill}>终止 Worker</button> </div> ); }; export default App;
2. 使用 worker-loader
在 Vue 3 中,可以通过 worker-loader 和 Web Worker 来处理耗时任务。以下是一个使用 Web Worker 的 Vue 3 示例:
配置 Webpack
在 webpack.config.js 中添加以下配置:
module.exports = {
module: {
rules: [
{
test: /\.worker\.js$/,
use: { loader: 'worker-loader' },
},
],
},
};
创建 Worker 文件
创建一个 Worker 文件 factorial.worker.js:
// factorial.worker.js
onmessage = (e) => {
const factorial = (n) => (n <= 1 ? 1 : n * factorial(n - 1));
postMessage(factorial(e.data));
};
在 Vue 组件中使用
在 Vue 3 组件中使用 Web Worker:
<template>
<div>
<button @click="calculateFactorial">计算阶乘</button>
<p v-if="result !== null">阶乘结果: {{ result }}</p>
</div>
</template>
<script>
import FactorialWorker from './factorial.worker.js';
export default {
data() {
return {
result: null,
worker: null,
};
},
methods: {
calculateFactorial() {
if (!this.worker) {
this.worker = new FactorialWorker();
this.worker.onmessage = (event) => {
this.result = event.data;
};
}
this.worker.postMessage(10);
},
},
beforeUnmount() {
if (this.worker) {
this.worker.terminate();
}
},
};
</script>
这两个库可以帮助开发者更高效地使用 Web Worker,简化复杂任务的实现。
→🐒

2205

被折叠的 条评论
为什么被折叠?



