web workerでの記事は、webpack環境(nuxt.js環境)や、typescriptでの記事が多く存在し、
所々詰まっていたので記事にします。
Web Worker の使用(MDN)
Vue.js で WebWorker を使う
[laravel-mix + Vue.js (ES) + WebWorker (TS)] (https://qiita.com/shohei_ot/items/61210e1012e9ae4f5d89)
これらの記事を参考にしました。
今回作成したgitリポジトリ
#導入
vue ui
等でvueを立ち上げたものとして、
プロジェクト直下で
npm install worker-loader
とし、worker-loaderを導入します。
そして、プロジェクト直下のvue.config.js
(無ければ作成し)に、
下記の内容を記述します
module.exports = {
chainWebpack: config => {
config.module
.rule('worker-loader')
.test(/\.worker\.js$/)
.use({
loader: 'worker-loader',
options: {
inline: true
}
})
.loader('worker-loader')
.end()
}
//...
}
#実行準備
次に、srcフォルダ直下に
workers
というフォルダと、worker1
というjsファイルを作成します。
(※名称はなんでも良いと思います。また、フォルダは存在していなくても良いと思います。)
src
|-assets
|-components
|- ...
|-workers
|-worker1.js
|-App.vue
|-main.js
このような構成になるかと思います。
次に、worker1.jsの中身を
addEventListener('message', e => {
const { data } = e
if (data && typeof data == 'number') {
return postMessage(data*data)
} else {
return postMessage(10)
}
})
export default {}
としてみます。
workerに投げられた変数が、int型の場合、二乗を返し、
それ以外の場合10を返す関数です。
次に、実際にvueファイルでworkerを呼び出します。
試しに、vuecliで生成されるHome.vueに書いていきます。
<script>
import Worker1 from 'worker-loader!@/workers/worker1'
export default {
name: 'Home',
components: {
},
data () {
return {
reload: 0
}
},
methods: {
workerTest: function () {
const worker = new Worker1()
worker.onmeessage = e => {
const { data } = e
this.reload = data
worker.terminate()
}
worker.postMessage(20)
}
}
}
</script>
このようにします。
import文に、worker-loader!
をpath名の前に挿入することに気をつけ、また、
worker.onmessageで、workerの処理が終わった場合(つまりpostMessageが返った場合)の処理を記述します。
今回の場合は、処理が終わり次第、this.reloadに代入し他で参照できるようにします。
また処理を終えたあとにworkerが存在する意味はないので、terminateで削除します。
(※importがlintに怒られるかもしれないので、その場合はruleに記述しましょう...)
#実行
<template>
<div class="home">
<button @click="workerTest()">worker!!</button>
{{ this.reload }}
</div>
</template>
実際に、このようにして試してみると...
実際に、workerを通して、値が変更されたのがわかります。
また、
workerTest: function () {
const worker = new Worker1()
worker.onmessage = e => {
const { data } = e
this.reload = data
}
worker.postMessage(20)
}
とし、
開発者ツールのSourcesをみると
実際にworkerが立っているのがわかります。
#other
##ループの中で実行
試しに
workerTestLoop: function () {
for (let i = 0; i < 10; i++) {
const worker = new Worker1()
worker.onmessage = e => {
const { data } = e
this.reload += data
worker.terminate()
}
worker.postMessage(20)
}
}