導入
JavaScriptはシングルスレッドで動作するため、重い計算処理や大量のデータ加工をメインスレッドで行うと、画面がフリーズしたり、UIの操作感が悪くなったりします。これを解決するのが「Web Worker」です。Worker.prototype.onmessageは、バックグラウンドスレッドからメインスレッドへデータを送り返すための非常に重要なAPIです。これを使えば、ユーザーの操作を止めることなく、裏側で複雑な処理を完結させることができます。
基礎知識
Web Workerは、メインのJavaScript実行環境とは別のスレッドでスクリプトを実行する機能です。メインスレッドとWorker間は、メッセージパッシングという仕組みで通信します。
onmessageは、Workerから送られてきたメッセージをメインスレッド側で受け取るためのイベントハンドラです。Worker側がpostMessageメソッドを実行すると、メインスレッド側のonmessageが発火し、データを受け取ることができます。
実装/解決策
実装の基本フローは以下の通りです。
1. メインスレッドでWorkerインスタンスを作成する。
2. Worker側で重い処理を行い、postMessageで結果を送信する。
3. メインスレッドのonmessageでその結果を受け取り、UIに反映させる。
サンプルプログラム
以下は、メインスレッドとWorker間の通信例です。
main.js(メインスレッド)
// Workerのインスタンスを作成
const worker = new Worker(‘worker.js’);
// 2. Workerからメッセージを受け取るためのハンドラを設定
worker.onmessage = function(event) {
// event.dataにWorkerから送られた値が入っています
console.log(‘計算結果を受け取りました:’, event.data);
};
// Workerに処理開始の合図を送る
worker.postMessage(100);
worker.js(Workerスレッド)
// 1. メインスレッドからのメッセージを監視
self.onmessage = function(event) {
const input = event.data;
// 重い計算のシミュレーション
const result = input 2;
// 3. 計算結果をメインスレッドへ送信
self.postMessage(result);
};
応用・注意点
現場で活用する際の重要な注意点は以下の3点です。
1. 通信コスト: postMessageはデータのコピー(構造化複製アルゴリズム)が行われます。巨大なデータを頻繁にやり取りするとオーバーヘッドが発生するため、可能な限り「Transferable Objects(ArrayBufferなど)」を使用して、メモリの所有権を移動させる方法を検討してください。
2. エラーハンドリング: Worker側でエラーが発生した際は、onmessageではなく onerror イベントが発火します。必ずonerrorも実装して、デバッグを容易にしましょう。
3. スコープの違い: Worker内ではDOM操作(documentやwindowなど)ができません。UIの更新は必ずメインスレッド側のonmessage内で行う必要があります。これらを守ることで、堅牢で快適なパフォーマンスを実現できます。