LoginSignup
27
14

More than 3 years have passed since last update.

Web Workerを実装してみる

Last updated at Posted at 2020-11-26

Web Workerって?

Web Worker とは、ウェブアプリケーションにおけるスクリプトの処理をメインとは別のスレッドに移し、バックグラウンドでの実行を可能にする仕組みのことです。時間のかかる処理を別のスレッドに移すことが出来るため、 UI を担当するメインスレッドの処理を中断・遅延させずに実行できるという利点があります。

by MDN

JSはシングルスレッドですので、本当の意味での並列処理が行えません。
なのでめちゃ重な処理を書いてしまうと、その他のボタンやら何やら効かなくなって、サイトが完全に固まってしまいます。
これを解消してくれるのがWeb Workerです。
昨今ではSPAなどによりでクライアント側で重たい処理をすることが増えていますので、ぜひ使いこなしておきたいと思っています。

現在ブラウザ側の対応はどうなってる?

スクリーンショット 2020-11-26 16.51.36.png
by Can I use
Opera以外はほとんどOKですね。

とにかくコード

index.js

const worker = new Worker('worker.js');

worker.addEventListener('message', (e) => {
  console.log('Workerから受け取ったデータは: ', e.data);
}, false);

worker.postMessage('Hello, world');
worker.js
self.addEventListener('message',(e) => {
  self.postMessage(e.data);
}, false);

ちなみに、workerのスクリプト内のグローバルはワーカー自身なので、下記のように書いてもOKです。

worker.js
addEventListener('message',(e) => {
  postMessage(e.data);
}, false);
結果
Hello, world

図でみるとわかりやすいです。

worker.png

それぞれのjsの onmesssage で、受信時/送信時のイベントを記述することができます。
受信データ/送信データはいずれも messsageイベントのdata属性から取得できます。
思ったよりも非常にシンプルです。

workerを終了したい場合。

worker.terminate();

terminateメソッドを使って直ちに終了することができます。

エラーハンドリング

Worker で実行時エラーが発生すると、 onerror イベントハンドラーが呼び出されます。これは、 ErrorEvent インターフェイスを実装している error イベントを受け取ります。

とのことです。(by MDN)
早速試してみましょう。

index.js
const worker = new Worker('worker.js');

worker.addEventListener('error', function (e) {
  console.log(e)
}, false);
worker.postMessage('Hello World');

worker.js
self.addEventListener('message', (e) => {

  throw new Error('何かしらのエラー')
  self.postMessage(e.data)
}, false)

結果:
スクリーンショット 2020-11-26 17.47.02.png

確かに 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/

27
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
14