Web Workerって?
Web Worker とは、ウェブアプリケーションにおけるスクリプトの処理をメインとは別のスレッドに移し、バックグラウンドでの実行を可能にする仕組みのことです。時間のかかる処理を別のスレッドに移すことが出来るため、 UI を担当するメインスレッドの処理を中断・遅延させずに実行できるという利点があります。
by [MDN] (https://developer.mozilla.org/ja/docs/Web/API/Web_Workers_API)
JSはシングルスレッドですので、本当の意味での並列処理が行えません。
なのでめちゃ重な処理を書いてしまうと、その他のボタンやら何やら効かなくなって、サイトが完全に固まってしまいます。
これを解消してくれるのがWeb Worker
です。
昨今ではSPAなどによりでクライアント側で重たい処理をすることが増えていますので、ぜひ使いこなしておきたいと思っています。
現在ブラウザ側の対応はどうなってる?
by Can I use
Opera以外はほとんどOKですね。
とにかくコード
const worker = new Worker('worker.js');
worker.addEventListener('message', (e) => {
console.log('Workerから受け取ったデータは: ', e.data);
}, false);
worker.postMessage('Hello, world');
self.addEventListener('message',(e) => {
self.postMessage(e.data);
}, false);
ちなみに、workerのスクリプト内のグローバルはワーカー自身なので、下記のように書いてもOKです。
addEventListener('message',(e) => {
postMessage(e.data);
}, false);
Hello, world
図でみるとわかりやすいです。
それぞれのjsの onmesssage
で、受信時/送信時のイベントを記述することができます。
受信データ/送信データはいずれも messsageイベントのdata属性から取得できます。
思ったよりも非常にシンプルです。
workerを終了したい場合。
worker.terminate();
terminate
メソッドを使って直ちに終了することができます。
エラーハンドリング
Worker で実行時エラーが発生すると、 onerror イベントハンドラーが呼び出されます。これは、 ErrorEvent インターフェイスを実装している error イベントを受け取ります。
とのことです。(by [MDN] (https://developer.mozilla.org/ja/docs/Web/API/Web_Workers_API))
早速試してみましょう。
const worker = new Worker('worker.js');
worker.addEventListener('error', function (e) {
console.log(e)
}, false);
worker.postMessage('Hello World');
self.addEventListener('message', (e) => {
throw new Error('何かしらのエラー')
self.postMessage(e.data)
}, false)
確かに ErrorEvent
をキャッチしています。
たくさんのプロパティがありますが、下記の3つが重要な項目です。
message
・・・ 人間用メッセージ
filename
・・・ エラー発生元のファイル名
lineno
・・・エラーが発生した行番号
スクリプト/ライブラリのimport
Workerスレッド側で何かインポートしたい場合は importScripts()
を使います。
ここで引数として指定したスクリプトが実行されます。
importScripts('test.js')
importScripts('foo.js', 'bar.js')
別ファイルでなく埋め込みでWorker
ファイルの記述を文字列化しBlobを生成、そしてそのURLを渡せばOK。
実際の実装ではあまり使わなそうだと思ったので例は割愛します。
注意点
Workerは直接DOMを操作できない点、そしてwindowのメソッドやプロパティは使用できない点に注意です。(worker自身がグローバルのため)
逆にそれ以外ならほとんど使用可能です。
MDNに使用できるクラス・関数がまとめられています。
https://developer.mozilla.org/ja/docs/Web/API/Web_Workers_API/Functions_and_classes_available_to_workers
また、Workerとやり取りする際のデータは共有しているのではなく、それぞれでコピーされています。
なので渡したデータをWorker側で操作しても、コピー元には関与できない点に注意です。
次回はService Workerについて学習予定です。
参考資料
https://www.html5rocks.com/ja/tutorials/workers/basics/
https://www.codit.work/notes/ytq5ztvnhceco3jn2bkb/