重い処理にはWebWorkerを使う

WRITER: y.harada
2020/08/31

Javascriptはシングルスレッドなため、重い処理を実行するとUIの描画処理がブロックされてしまうが、

WebWorkerを使うことでこの問題を解決することができる。

WebWorkerとは

ここに書いてある通り

https://developer.mozilla.org/ja/docs/Web/API/Web_Workers_API/Using_web_workers

WebWorker は、ウェブコンテンツがスクリプトをバックグラウンドのスレッドで実行するためのシンプルな手段です。 Worker スレッドは、ユーザーインターフェイスを妨げることなくタスクを実行できます。

つまりWebWorkerを用いることでマルチスレッドで並列処理を実現することができます。

WebWorkerの使い方

Workerオブジェクトの生成

WebWorkerのパスを指定してWorkerコンストラクタを呼び出すだけ

メインスレッドとWebWorkerの送受信

メッセージシステムを使用してメインスレッドとWebWorkerでデータのやり取りをします

メインスレッドからWebWorkerに送信する

WebWorkerで受信する

messageイベントListenします

WebWorkerからメインスレッドに送信する

メインスレッドで受信する

メインスレッドもWorkerもpostMessageとmessageイベントを使用してメッセージを送受信します

具体的にWebWorkerの効果を試してみます

0.1秒の間隔で描画し続けるタイマーと

1秒間のループ数をカウントし描画するボタンがあります

(WorkerではDOMにアクセスできないのでメインスレッドで結果を受け取ってからDOMを更新する必要があります)

メインスレッドで実行

メインスレッドで実行すると結果が描画されるまではタイマーの描画が止まってしまいます

WebWorkerで実行

Workerで実行するとタイマーの描画は止まらずに結果を描画することができます

このように重い処理をWorkerで実行することで、メインスレッドの処理を妨げず、パフォーマンスを向上させることができます

WorkerをESモジュールのように扱う

ESモジュールを利用してる環境では、WebWorkerをモジュールのように扱うことのできるloaderがあります

https://github.com/developit/workerize-loader

Workerでは関数をexportするだけ

メインスレッドではWorkerをインポートして

インスタンスを生成してexportした関数を実行するだけ

メッセージのやり取りが簡単な上、async/awaitも動作するのでおすすめです

y.harada

y.harada

Unityエンジニア
Reactが好き