JavaScript アドバンス

Web Workers API

1. Web Worker とは何か?

Web Worker(ウェブワーカー)は、ページのパフォーマンスに影響を与えることなく、バックグラウンドで実行される JavaScript です。

通常、HTML ページ内でスクリプトを実行すると、そのスクリプトの処理が終了するまでページは「応答なし」の状態になります。これは JavaScript がメインスレッドで動作し、UI の描画と同じリソースを共有しているためです。

Web Worker は、他のスクリプトから独立してバックグラウンドで動作する JavaScript です。そのため、ワーカーが複雑な計算を実行している間でも、ユーザーはクリックや項目の選択といった操作を通常通り続けることができます。

2. ブラウザのサポート状況

以下の表は、Web Worker をフルサポートしている主要なブラウザの最小バージョンを示しています。

Chrome 4.0Edge (IE) 10.0Firefox 3.5Safari 4.0Opera 11.5
(2010年1月)(2012年9月)(2009年6月)(2009年6月)(2011年6月)

3. Web Worker のサポート確認

Web Worker を生成する前に、ユーザーのブラウザが対応しているかどうかを確認する必要があります。

if (typeof(Worker) !== "undefined") {
  // Web Worker がサポートされている場合の処理
  // コードをここに記述.....
} else {
  // Web Worker がサポートされていない場合の処理
  console.log("お使いのブラウザは Web Worker をサポートしていません。");
}

4. Web Worker ファイルの作成

次に、外部 JavaScript ファイルにワーカーとしての処理を記述します。ここでは、数値をカウントアップするシンプルなスクリプトを作成し、demo_workers.js という名前で保存します。

// demo_workers.js の内容
let i = 0;

function timedCount() {
  i++;
  // メッセージをメインスレッド(HTMLページ)に送信
  postMessage(i);
  // 500ミリ秒ごとに繰り返す
  setTimeout("timedCount()", 500);
}

timedCount();

このコードで最も重要なのは postMessage() メソッドです。これは、バックグラウンドで処理したデータを HTML ページに送り返すために使用されます。

       注記: 通常、Web Worker はこのような単純なスクリプトではなく、より CPU 負荷の高い(重い)タスクに使用されます。

5. Web Worker オブジェクトの作成

ワーカーファイルが用意できたら、HTML ページ側から呼び出す必要があります。
以下のコードは、ワーカーが既に存在するか確認し、存在しない場合は新しい Web Worker オブジェクトを生成して demo_workers.js を実行します。

if (typeof(w) == "undefined") {
  w = new Worker("demo_workers.js");
}

これにより、ワーカーとの間でメッセージの送受信が可能になります。

6. onmessage イベントリスナー

Web Worker がメッセージ(データ)を送信すると、HTML ページ側の onmessage イベントリスナー内のコードが実行されます。

w.onmessage = function(event) {
  // ワーカーから送られたデータは event.data に格納される
  document.getElementById("result").innerHTML = event.data;
};

7. Web Worker の終了 (Terminate)

Web Worker オブジェクトが作成されると、外部スクリプトの処理が終了した後でもメッセージを待ち受け続けます。ブラウザやコンピュータのリソースを解放するために、ワーカーを終了させるには terminate() メソッドを使用します。

w.terminate();

8. Web Worker の再利用

ワーカーを終了させた後、ワーカー変数を undefined に設定することで、再度同じ仕組みを利用できるようになります。

w = undefined;

9. 完全な実装コード例

これまでに解説したワーカー側のコード(.jsファイル)と、HTML ページ側のコードを統合すると以下のようになります。

実装例 (HTML)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Web Worker 実装例</title>
</head>
<body>

<p>カウント結果: <output id="result"></output></p>
<button onclick="startWorker()">ワーカー開始</button>
<button onclick="stopWorker()">ワーカー停止</button>

<script>
let w;

function startWorker() {
  // ブラウザのサポートチェック
  if (typeof(Worker) !== "undefined") {
    // ワーカーオブジェクトが未生成の場合のみ生成
    if (typeof(w) == "undefined") {
      w = new Worker("demo_workers.js");
    }
    // ワーカーからのデータ受信
    w.onmessage = function(event) {
      document.getElementById("result").innerHTML = event.data;
    };
  } else {
    document.getElementById("result").innerHTML = "Web Worker 非対応です。";
  }
}

function stopWorker() {
  // ワーカーを終了させてリソースを解放
  if (typeof(w) !== "undefined") {
    w.terminate();
    w = undefined;
  }
}
</script>

</body>
</html>