博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
vue-worker的介绍和使用
阅读量:7088 次
发布时间:2019-06-28

本文共 5037 字,大约阅读时间需要 16 分钟。

vue-worker把复杂的web worker封装起来,提供一套非常简明的api接口,使用的时候可以说像不接触worker一样方便。那么具体怎么使用呢?

安装

npm i -S vue-worker

 

注册

import Vue from 'vue'import VueWorker from 'vue-worker'import App from 'App.vue'Vue.use(VueWorker)new Vue({   el: '#app',  render: h => h(App) })
注册之后,你可以像this.$store一样使用this.$worker

使用

export default { name: 'worker-test', data() {   return {    worker: null,   } }, mounted() {   // 通过this.$worker.run这个方法,跑起一个worker,   // worker是在另外的线程里面跑的,所以可以在run的第一个参数函数里面执行一个非常大计算的操作   // run方法像Promise一样提供.then和.catch,then的参数就是run第一个参数函数的返回值   this.worker = this.$worker.run(n => n + 10, [2])    .then(res => console.log(res))    .catch(e => console.log(e)) }, destroyed() {   // 通过赋值null的方式,释放掉worker引用,这样就可以关闭worker,这是作者在github上说的   this.worker = null },}

 

API介绍

下面来详细介绍一下vue-worker的几个api,也就是方法method。

.run(fun, [...args])

上面已经看到了这个方法,而且也有注释说明。注意第二个参数是一个数组,数组的个数和第一个参数fun的形参个数是一样的。

你可能会有一个疑问:直接在fun函数体内使用当前变量不就好了么?js本身的全局变量特性在这里不能用?这是因为worker是在另外一个线程中运行,跟当前页面内的js脚本不是在同一个线程,不共享内存空间,所以直接在fun函数体里面使用另外一个线程的变量是找不到的,所以要通过函数参数的形式进行传递。而传递的实质,是使用了worker的postMessage方法,把第二个参数当做postMessage的内容,具体你可以阅读的源码。

run是一次性的,跑完这次,worker线程就会被关掉。想要持久化worker,可以使用下面的create来创建。

.create([...actions])

这个方法让你创建一个worker对象(注意不是worker实例,你无法通过该对象直接操作worker,这个实例仅仅是一个js object,提供了几个属性接口)。

actions是一个数组,数组的每个元素是一个含有两个属性的对象:

export default {  name: 'worker-test',  data() {    return {     worker: null,    }  },  created() {    this.worker = this.$worker.create([      {        message: 'pull-data',        func(data) {          data.forEach(...)          return data        },      },      {        message: 'run-task',        func(id) {          //...        },      }    ])  },  mounted() {    let data = ...    this.worker.postMessage('pull-data', [data])      .then(res => console.log(res))  },  destroyed() {    this.worker = null  },}

实际上.run方法是create方法和postMessage方法的合体,一次性把两个方法的事都做了。

.postMessage(messageid, [...args])

这个在上面的代码里面已经演示了。它不是this.$worker的方法,而是通过this.$worker.create之后得到的object的一个方法。使用这个方法跟worker原生的方法很像,当然,这里的messageid就是上面actions数组里面的某个对象的message字段对应的那个。而args就是你要传递的数据。

你可能又会问了,这里的[..args]是一个参数,还是说里面的元素才是参数。其实很简单,[...args]被用作了.apply的第二个参数:func.apply(null, [...args]),所以,...args对应的就是func的参数。

.postAll([...args])

这里的postAll和上面的postMessage一样,是create之后的那个object的一个方法,而不是this.$worker的,所以使用的时候,也只能用在create之后。

它的参数是一个数组,但是这个数组的元素有三种形式,一种是不传,一种是string:messageid,另一种是{message, [...func_args]}。其实都很好理解。

不传

代表所有的actions都执行一次postMessage。

[string:messageid]

代表对应的messageid的那个action被执行postMessage。

[{message, [...func_args]}]

给指定的messageid传参数。

export default {  name: 'worker-test',  data() {    return {      worker: null,    }  },  created() {    this.worker = this.$worker.create([      {        message: 'pull-data',        func(data) {          data.forEach(...)          return data        },      },      {        message: 'run-task',        func() {          //...        },      }    ])  },  mounted() {      // 1. 不传    this.worker.postAll().then([res1, res2] => {})      // 2. 字符串形式    let data = ...    this.worker.postAll(['run-task']).then([res] => {}) // 仅'run-task'被postMessage      // 3. 对象形式(混合形式)    this.worker.postAll([      'run-task',      {        message: 'pull-data',        args: [data],      },    ]).then([res1, res2] => {})  },  destroyed() {    this.worker = null  },}

 

比较难把握的就是,这里所有的传入都要采用数组的形式,理解上需要稍微思考下。

.register(action || [...actions])

同理,也是在<worker>的object对象上的方法。当你使用create之后,发现你的worker任务不够用,要追加一个action或多个,那么可以使用register来追加。action(s)和create是一模一样的。

.unregister(message || [...messages])

和register有点像,意思是当你某一个任务不想要了,可以通过unregister来取消这个任务。参数和register不一样,直接使用messageid作为参数即可。

export default {  name: 'worker-test',  data() {    return {      worker: null,    }  },  created() {    this.worker = this.$worker.create([      {        message: 'pull-data',        func(data) {          data.forEach(...)          return data        },      },      {        message: 'run-task',        func() {          //...        },      }    ])  },  mounted() {    // 1. 不传    this.worker.postAll().then([res1, res2] => {})      // 2. 字符串形式    let data = ...    this.worker.postAll(['run-task']).then([res] => {}) // 仅'run-task'被postMessage      // 3. 对象形式(混合形式)    this.worker.postAll([      'run-task',      {        message: 'pull-data',        args: [data],      },    ]).then([res1, res2] => {      // 注意,这里then里面执行的是在主js线程里面执行的,所以可以直接用this.worker      this.worker.unregister('run-task')      // 当你注销掉了,那么下回你在post到run-task这个任务消息时,就啥都不会发生了    })  },  destroyed() {    this.worker = null  },}

关闭worker

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

原理

web worker是通过一个浏览器提供的Worker对象来创建的,创建的时候要传入指定的javascript文件作为worker线程的执行脚本。worker线程内的脚本有一些限制,比如只能拿到window.navigator的信息,不能拿到完整的window对象。重点是,这里我们没有提供一个js文件传入worker线程,vue-worker是怎么做到的呢?它利用了Blob来创建一个可执行的二进制上下文,在通过这个上下文来调用我们传入的function,就好像在内存中虚拟了一个内容是我们传入的function的js文件一样。具体的源码可以看

转载地址:http://gufql.baihongyu.com/

你可能感兴趣的文章
【Android每日一讲】2012.11.06 Android变脸 - 主题(Theme)实现
查看>>
redis 系列12 哈希对象
查看>>
QTP使用心得
查看>>
js/jq ajax+数组。个人整理
查看>>
mac 下批量转换文件类型
查看>>
何为DOM对象
查看>>
linux的yum仓库配置
查看>>
XSUPERSMS COME ON
查看>>
[JS2] JS是弱类型
查看>>
企业搜索引擎开发之连接器connector(二十四)
查看>>
数学图形(1.9)悬链线
查看>>
有上下界的网络流问题
查看>>
AspectJ获取方法注解的信息
查看>>
HDU 4902 Nice boat(线段树)
查看>>
Codeforces Round #114 (Div. 1) E. Wizards and Bets 高斯消元
查看>>
怎样调通微信支付及微信发货通知接口(Js API)
查看>>
Android 属性动画(Property Animation) 全然解析 (下)
查看>>
推断汉字正則表達式更严谨方法!
查看>>
如何避免误删CleanMyMac语言文件
查看>>
Linux下免安装mysql
查看>>