Webteko 第11回で Web Workers について発表した

1/23(土)に神戸で Webteko(ウェブテコ)第11回が開催された(告知ページ)

今回のテーマは「HTML5 と CSS3」ということで、僕も Web Workers について発表してきた。

発表内容

サンプルコード

デモとして、バックグラウンドで足し算を行う JavaScript コードを紹介した。あと、1%分完了するたびに進捗状況を表示してる。計算してる途中でもブラウザが固まらないってのがポイント。

まずこれが HTML ファイル。入力ボックス、ボタン、結果表示欄があるだけ。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Web Workers を使って足し算する</title>
  <script type="application/javascript" src="main.js"></script>
</head>
<body>
  <h1>Web Workers を使って足し算する</h1>
  <p>1 から <input type="text" id="num" value="10"> までの合計</p>
  <button id="run">計算</button>
  <p><span id="progress">0</span> %</p>
  <p id="result"></p>
</body>
</html>

次にこれが main.js。メインの JavaScript コードで、こいつが親になって新しい Web Workers を作成する。

(function() {
  function init() {

    function setText(elem, text) {
      if (! elem.firstChild) {
        elem.appendChild(document.createTextNode(""));
      }
      elem.firstChild.data = text;
    }

    function run() {
      var num = parseInt(document.getElementById("num").value, 10);

      // 計算を行うワーカーを生成
      var worker = new Worker("worker.js");

      // ワーカーから結果を受け取る
      worker.onmessage = function(event) {
        if (event.data.isDone) {
          // 計算が完了した場合
          var retElem = document.getElementById("result");
          setText(retElem, event.data.value.toString());
        } else {
          // 計算が完了していない場合
          var progressElem = document.getElementById("progress");
          setText(progressElem, event.data.value.toString());
        }
      };

      // ワーカーに計算させる
      worker.postMessage(num);
    }

    document.getElementById("run").
      addEventListener('click', run, false);
  }

  window.addEventListener('load', init, false);
})();

最後に、これが worker.js。こいつがワーカーで、バックグラウンドで行う処理が書いてある。

onmessage = function(event) {
  var p = 0;
  var current_p;
  var num = event.data;
  var result = 0;

  for (var i = 0; i <= num; i++) {
    current_p = Math.floor(i * 100 / num);
    if (current_p > p) {
      p = current_p;
      // 現在の進捗を通知する
      postMessage({isDone: false, value: p});
    }

    result += i;
  }
  // 計算結果を返す
  postMessage({isDone: false, value: 100});
  postMessage({isDone: true, value: result});
};

このコードは Firefox 3.5 で動作確認した。たぶん他のブラウザでは動かない(worker.js の postMessage でオブジェクトを渡してるとこが動かない)。

どこで使うか

Web Workers の使いどころなんだけど、現状では役に立つ場面は少ないと思う。何でかというと

つまり、現状の JavaScript の処理で重いものといえば DOM の操作と XMLHttpRequest(Ajax) なんだけど、その二つは Web Workers の恩恵が無い。で、それ以外で応答性が悪くて困るってことはあんまりないんじゃないのかな。

でも、今 JavaScript で出来ることをどんどん広げよう、という動きがある。画像、動画処理だったり、ローカルでデータベースの処理だったり、いかにも重そうなことをやろうとしてる。また、それにともなって圧縮や暗号化の処理が JavaScript で必要になるかもしれない。

そんなときには Web Workers を使うときっと快適になるよ。

参考資料

今回は以下のページを参考にした。

whatwg のドキュメント。

マイコミジャーナルの記事。足し算する、ってとこはこのページをまねした。

MDC のドキュメント。Firefox での Web Workers について書いてある。