呢呢 Blog 呢呢 Blog
首页
  • 前端

    • web Worker使用笔记
  • 博客搭建

    • 快速上手
文集
  • 前端公用方法
关于
  • 网站
  • 资源
  • Vue资源
  • 友情链接
GitHub
首页
  • 前端

    • web Worker使用笔记
  • 博客搭建

    • 快速上手
文集
  • 前端公用方法
关于
  • 网站
  • 资源
  • Vue资源
  • 友情链接
GitHub
  • 前端

    • vscode插件同步
    • markdown语法
    • webpack笔记
    • web Worker使用笔记
      • 一、前言
      • 二、基本用法
        • 主线程
        • 子线程 work.js
      • 三、vue-worker
        • 1、安装
        • 2、注册 main.js
        • 3、使用
        • 4、关闭worker 问题
        • 5、原理
    • vue-cli4设置打包相对路径
    • vue-cli4配置scss全局变量
    • TOAST UI Editor 使用方法
  • 博客搭建

  • 微前端

  • Cesium天地图

  • bug记录

  • vuepress

  • 浏览器架构及原理

  • photoshop

  • vue3+vite

  • react

  • 编程
  • 前端
Ni Ni
2021-02-03

web Worker使用笔记

# 一、前言

JavaScript 语言采用的是单线程模型,也就是说,所有任务只能在一个线程上完成,一次只能做一件事。前面的任务没做完,后面的任务只能等着。 随着电脑计算能力的增强,尤其是多核 CPU 的出现,单线程带来很大的不便,无法充分发挥计算机的计算能力。

Web Worker 的作用,就是为 JavaScript 创造多线程环境。

  • Worker 线程在后台运行,两者互不干扰。
  • Worker 线程完成计算任务,再把结果返回给主线程
  • Worker 线程一旦新建成功,就会始终运行,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭

Web Worker 有以下几个使用注意点。

(1).同源限制

分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。

(2). DOM 限制

Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象, 也无法使用document、window、parent这些对象。但是,Worker 线程可以使用navigator对象和location对象

(3). 通信联系

Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。

(4). 脚本限制

Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。

(5). 文件限制

Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。

# 二、基本用法

# 主线程

var worker = new Worker('work.js'); #新建线程
/**
 * #主线程向 子线程worker发送消息
 * @params string|Object|Array|Boolean|binary 等等
 */
worker.postMessage('Hello World'); 

接收子线程发回来的消息
worker.onmessage = function (event) {
  console.log('Received message ' + event.data);
  //to do something ...
}
错误处理
worker.onerror(function (event) {
  console.log([
    'ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message
  ].join(''));
});

关闭worker,使用完毕,为了节省系统资源,必须关闭 Worker。
worker.terminate();#主线程
worker.postMessage({cmd:'close'});# Worker 线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 子线程 work.js

# Worker 内部如果要加载其他脚本,可以使用importScripts(),如果无脚本文件加载删除即可
importScripts('script1.js', 'script2.js');

监听`主线程`传递过来的消息
this.addEventListener('message', function (e) {
   var data = e.data;
  switch (data.cmd) {
    case 'close':
      self.close(); // 关闭 worker.
    default:
       this.postMessage('You said: ' + e.data);
}, false);

1
2
3
4
5
6
7
8
9
10
11
12
13

更多详细内容,参考大佬链接 阮一峰 Web Worker使用教程

# 三、vue-worker

# 1、安装

npm i -S vue-worker
1

# 2、注册 main.js

import VueWorker from 'vue-worker'
Vue.use(VueWorker)
1
2

# 3、使用

1). run是一次性的,跑完这次,worker线程就会被关掉,适用只执行一次的大计算操作

export default {
  data() {
	  return {
	    worker: null
	  }
 	},
  mounted() {
    /**
     * 开启新的线程
     * @params1 n=>{} = worker 中的addEventListener
     * @params2 [2] = worker.postMessage
     */
    this.worker = this.$worker.run(n => {
      return n+10 
    }, [2])
    .then(res =>{// worker中的wroker.onmessage
      //do something
    })
    .catch(e => console.log(e)) 
  }, 
  destroyed() {
    this.worker = null //关闭worker
  },
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

2). 持久化worker

export default {
  data() {
	  return {
	    worker: null
	  }
 	},
  created() {
  	//create 的内容适用Blob来创建一个可执行的二进制上下文
    this.worker = this.$worker.create([
      {
        message: 'task1',
        func(data) {
          // do something
          return data
        },
      },
      {
        message: 'task2',
        func(id) {
          //do something
          return id
        },
      }
    ])
  }, 
  mounted(){
    //只执行task1
    this.worker.postMessage('task1', [data]).then(res => console.log(res))
    //create的所有任务都执行
    this.worker.postAll().then((data))=> {})
    //执行`task1` `task2`
    this.worker.postAll([{ message: 'task1', args: [{ name: 'li si' }] },{ message: 'task2', args: [{ name: 'zhang san' }] }]).then((data)=> {})
    
    //不想要其中一个任务时 注销task1
    this.worker.unregister('task1')
    //追加 task3
    this.worker.register({ message: 'task3', func: (data) => {return data} })
  },
  destroyed() {
    this.worker = null //关闭worker
  },
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# 4、关闭worker 问题

插件的作者指出,你是没办法拿到worker原始实例的,所以也就无法调用worker.terminate()或者在worker线程内部执行self.close()来关闭worker。 create方法创建的不是worker实例,所以它内部有,但是没有暴露出来。所以插件没有关闭worker的方法,你直接把worker对象释放掉即可。 我翻阅了源码,发现它只在调用run方法时才使用close,执行完run之后worker会被close,但是如果你使用create创建的worker,是不会被close的它会一直存在,直到你关闭浏览器。

# 5、原理

  • web worker 通过worker对象创建的,传入javascript文件作为worker的执行脚本

  • vue-worker 通过Blob来创建一个可执行的二进制上下文,在通过这个上下文来调用我们传入的function,就好像在内存中虚拟了一个内容是我们传入的function的js文件一样

编辑
上次更新: 2021/07/22, 09:07:42
webpack笔记
vue-cli4设置打包相对路径

← webpack笔记 vue-cli4设置打包相对路径→

最近更新
01
react全家桶搭建全家桶模板
10-19
02
react学习到搭建一个全家桶的基础模板
10-09
03
202108自修图
09-24
更多文章>
Theme by Vdoing | Copyright © 2020-2021 Ni Ni | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×