众所周知,Javascript是运行在单线程环境中,也就是说无法同时运行多个脚本。假设用户点击一个按钮,触发了一段用于计算的Javascript代码,那么在这段代码执行完毕之前,页面是无法响应用户操作的。但是,如果将这段代码交给Web Worker去运行的话,那么情况就不一样了:浏览器会在后台启动一个独立的worker线程来专门负责这段代码的运行,因此,页面在这段Javascript代码运行期间依然可以响应用户的其他操作。
Web Worker简介
Web Worker 是HTML5标准的一部分,这一规范定义了一套 API,它允许一段JavaScript程序运行在主线程之外的另外一个线程中。
值得注意的是, Web Worker 规范中定义了两类工作线程,分别是专用线程Dedicated Worker和共享线程 Shared Worker,其中,Dedicated Worker只能为一个页面所使用,而Shared Worker则可以被多个页面所共享。
Web Worker 使用注意如下常见的几点:
同源限制:分配给 Worker线程运行的脚本文件,必须与主线程的脚本文件同源。2. DOM限制:Worker所在的线程它不能操作window,document这样的对象,也就是说worker线程不能操作dom对象,但是worker线程可以操作业务逻辑,然后把操作后的结果返回给主线程,主线程再去做相关的DOM操作。
文件限制:Worker线程无法读取本地文件,也就是说不能打开本机的文件系统(如:file://) 这样的,它所加载的脚本,必须来自网络。
1.在webpack中配置 Web Workers
|--- web-worker项目 | |--- node_modules # 安装的依赖包 | |--- public | | |--- images # 存放项目中所有的图片 | | |--- js | | | |--- main.js # js 的入口文件 | | | |--- test1.worker.js # worker 线程的js文件 | | |--- styles # 存放所有的css样式 | | |--- index.html # html文件 | |--- package.json | |--- webpack.config.js
- 在项目中安装 worker-loader 依赖,如下命令所示
- 在webpack配置中添加如下配置:
module.exports = { module: { rules: [ { test: /\\.worker\\.js$/, // 以 .worker.js 结尾的文件将被 worker-loader 加载 use: { loader: 'worker-loader', options: { inline: true // fallback: false } } } ] } }
如上正则匹配的是以 以 .worker.js 结尾的文件将被 worker-loader 加载, 也就是说我们在项目中我们的worker文件名可以叫 test.worker.js 类似这样的名字,或其他的,只要保证 xxx.worker.js 这样的文件名即可。
在上面配置中,设置 inline 属性为 true 将 worker 作为 blob 进行内联;内联模式将额外为浏览器创建 chunk,即使对于不支持内联 worker 的浏览器也是这样的;
在本地开发中,我们会使用 webpack-dev-server 启动本地调式服务器,如果只有上面的配置的话,我们可以在控制台中会报如下的错误
"Uncaught ReferenceError: window is not defined";
要解决如上的错误的话,我们需要在我们的webpack配置文件下的out下,加一个属性 globalObject: 'this'; 如下代码:
module.exports = { output: { globalObject: 'this' } }
module.exports = { output: { filename: process.env.NODE_ENV === 'production' ? '[name].[contenthash].js' : '[name].js', // 将输出的文件都放在dist目录下 path: path.resolve(__dirname, 'dist'), publicPath: '/', globalObject: 'this' } }
来看下我们的 public/js/main.js 代码如下:
// 加载css样式 require('../styles/main.styl'); import Worker from './test1.worker.js'; // 创建worker实列 var worker = new Worker(); // 向worker线程发送消息 worker.postMessage('主线程向worker线程发送消息'); // 监听worker线程发送回来的消息 worker.onmessage = function(e) { console.log('监听worker线程发送回来的消息如下所示:') console.log(e); };
public/js/test1.worker.js(子线程)的代码如下所示:
// 监听消息 onmessage = function(e) { console.log('监听到的消息为:' + e.data); } const msg = '工作线程向主线程发送消息'; // 发送消息 postMessage(msg);
运行如下
如上代码,我们首先创建了一个worker实列,如代码:var worker = new Worker(); 然后他就会调用 test1.worker.js 代码,该worker中的代码会首先给主线程发送消息,消息文本为: '工作线程向主线程发送消息'; 然后我们的主线程中会通过 worker.onmessage 事件来监听子线程的消息,因此我们第一次打印出来为如下代码的消息:
worker.onmessage = function(e) { console.log('监听worker线程发送回来的消息如下所示:') console.log(e); };
然后我们的主线程才会向子线程发送消息,如下代码:
// 向worker线程发送消息 worker.postMessage('主线程向worker线程发送消息');
然后 test1.worker.js 代码中的 onmessage 就能监听到消息,如下所示:
// 监听消息 onmessage = function(e) { console.log('监听到的消息为:' + e.data); }
最后就会打印出信息如下:"监听到的消息为:主线程向worker线程发送消息"。
标签:web,基本原理,workers,worker,js,---,Worker,线程,消息 From: https://www.cnblogs.com/xgn666/p/17032837.html