web worker实际使用
web worker的好处
相信大家都比较熟悉,比如:
- 为js创造多线程环境,一些 计算量大的 耗时的 任务,可以用web worker单独开线程去跑,不会影响到主线程的运行
- 这样主线程(ui交互渲染等)就不会被阻塞,页面流畅
实际如何使用呢?
首先要理解一个区别,主线程和子线程是分别独立,不要混在一起去理解
上一段代码,方便理解:
// 文件的目录结构:├── index.html└── poorWorker.js (穷人打工仔,worker,干活的人)
这是主线程:index.html
<script>const worker = new Worker('./poorWorker.js');worker.postMessage("我是主进程, 我是boss,我传给worker线程消息: 赶紧干活!!");worker.onmessage = msg => {console.log(msg)console.log("我是主进程,我是boss,接收的子线程的数据:", msg.data);worker.terminate(); // 关闭主线程};worker.onerror = e => {console.log(e)};</script>
这是子线程:poorWorker.js
// importScripts('./hello2.js', 'http://xxx/a.js'); // 此处可以指出多脚本, 加载的脚本不支持跨域!!// self 代表子线程自身,即子线程的全局对象。// self可以换成this或不写,也可以实现执行。此处用self用于区分子线程worker// 监听主线程传过来的信息self.onmessage = e => {console.log(e)console.log('我是子线程, 我在工作, 我是worker, 我收到主线程传来的信息:', e.data)// do something}// setTimeout非必须,此处模拟,worker干了个耗时的活,2s后告诉主线程(老板)活已经干完ok了。setTimeout(() => {// 发送信息给主线程self.postMessage('我是子线程, 我在工作, 我是worker, 工作已经完成 ok')closeSon()}, 2000)// 关闭worker线程function closeSon () {return self.close()}
打印效果如下:

骚操作写法介绍(更推荐上面的写法)
正常情况,推荐上面的写法:把worker部分,单独分离成一个.js文件。
但强行把worker部分,不分离成.js,强行写在index.html内,也可以做到
这是 index.html
<script>// 此处把上面的poorWorker.js放到data中const data = `// importScripts('./hello2.js', 'http://xxx/a.js'); // 此处可以指出多脚本, 加载的脚本不支持跨域!!// self 代表子线程自身,即子线程的全局对象。// self可以换成this或不写,也可以实现执行。此处用self用于区分子线程worker// 监听主线程传过来的信息self.onmessage = e => {console.log(e)console.log('我是子线程, 我在工作, 我是worker, 我收到主线程传来的信息:', e.data)// do something}// setTimeout非必须,此处模拟,worker干了个耗时的活,2s后告诉主线程(老板)活已经干完ok了。setTimeout(() => {// 发送信息给主线程self.postMessage('我是子线程, 我在工作, 我是worker, 工作已经完成 ok')closeSon()}, 2000)// 关闭worker线程function closeSon () {return self.close()}`;const blob = new Blob([data]); // 把poorWorker.js的内容转成二进制const url = window.URL.createObjectURL(blob); // 把二进制转成一个本地链接const worker = new Worker(url); // 利用了new Worker()只接受url的特点// ... 后面的代码同上worker.postMessage("我是主进程, 我是boss,我传给worker线程消息: 赶紧干活!!");worker.onmessage = msg => {console.log(msg)console.log("我是主进程,我是boss,接收的子线程的数据:", msg.data);worker.terminate(); // 关闭主线程};worker.onerror = e => {console.log(e)};</script>
最后(断开)
Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。
但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。
码字不易,点赞鼓励
