HTML5のWeb Workersで並列処理を使いこなしてみよう!

html5

近年は、html5の台頭によって「html5+css+javascript」によるアプリケーションの開発などの案件もものすごく増えてきたのを感じます。それによってjavascriptが注目を浴びまくったため、javascriptでも高負荷な計算の処理をしたい・・しかしシングルスレッドだと処理が重くなるとクラッシュしてしまう・・じゃあjavascriptでも並列処理が必要だよね!!ってのも自然な流れだと思います。そこで登場したのが、WebWorkersです。

Web Workersとは

Web Workersは、JavaScriptでクライアント側とは別にバックグラウンドでのスクリプト実行を可能にする機能です。
通常はプログラムの処理は上から順番に処理されますが、その処理が実行し終えるまで次の処理には行きません。そのためユーザーは処理を待つことになってしまいます。そこでWeb Workersを利用して複雑な処理をバックグラウンドで走らせて並列処理をさせ分散させることで付加を減らすことができるという優れもの!!

簡単なサンプルで、テキストボックス1とテキストボックス2に入力したデータをワーカー側でくっつけて返すという単純な処理。番号振ってあるところをメモ。


//①ワーカが使えるかチェック
if(!window.Worker){
    document.getElementById("res").innerHTML="web workerが使えん";
  return;
}else{
document.getElementById("res").innerHTML="web workerが使えるよ";
}

//ボタンにイベントの設定する
var btn=document.getElementById("btn");
btn.addEventListener("click",sender,false);

var rbtn=document.getElementById("resetbtn");
rbtn.addEventListener("click",resettext);


//②ワーカーインスタンスを作成する
var worker=new Worker("http://jsrun.it/assets/4/s/n/c/4sncZ");

//クリックした時の処理
function sender(event){
  var val1=document.getElementById("t1").value;
  var val2=document.getElementById("t2").value;
    alert("データをworkerに送ります");
  //③ワーカーにデータを送る
    worker.postMessage({"val1":val1,"val2":val2});
  //
}
                  
//④ワーカー側の結果の受信した処理
worker.onmessage=function(e){
    alert("workerから処理をしてデータを受け取ります");
    document.getElementById("res").innerHTML=e.data;
                       }
//データを初期化する
function resettext(){
document.getElementById("res").innerHTML="初期化しました";
}
      

Web Workersの手順

①ワーカー使えるかチェック

まずは、ブラウザでWeb Workersが使用できるかを確認します。これはまだブラウザでばらつきがあるからです。
IEは10から実装されるということですが。

②ワーカーインスタンスを作成する

ワーカーインスタンスを作成するにはコンストラクタの引数に、実際のロジックを表すJavaScriptファイを指定するだけです。
*後々出てくるサンプルはJS DO ITのサービスを利用しているのでJavaScriptのファイルをアップロードしたパスを指定しています。

③ワーカーにデータを送る

ワーカーにデータを送るには生成したワーカーインスタンスのPostMessageメソッドを利用する。
今回の場合は送るボタンがクリックされたらPostMessageメソッドに取得したテキストボックスの値をJSON形式にして送ってます。

ちなみに、ワーカーのイベントは下記のイベントハンドラがあるようです。

onmessage データを受信した際のイベントハンドラ
onerror エラー発生時のイベント・ハンドラ
postMessage データを送信する際のイベントハンドラ
terminate() ワーカーを停止させるイベントハンドラ

④ワーカー側の結果の受信した処理

③のデータを送った後はワーカーのJavaScriptが実行されるのだが、混乱するので先にワーカーでの処理の後に送られてくるデータを受信する方の説明。

ワーカーからのデータを受信するには③で記載したイベントハンドのonmessageメソッドを使用すれば受信できます。

そして受信したデータですが、ワーカーインスタンスのonmessageメソッドの関数の引数に設定されているイベントオブジェクト(e)もしくは(event)のdataプロパティに格納されている。

worler.onmessage=function(e){
var resdata=e.data  //dataプロパティに格納されている。
}

上記のonmessageメソッドは、ワーカー側でPostMessageイベントが実行されるとonmessageメソッドが発生される仕組みになっている。

ワーカー側のスクリプト

今度は上記の呼び出し元の③の処理の後のワーカー側のスクリプトを記載。


//ワーカー側でデータを受信したときの処理
onmessage=function(e){
	var d=e.data;
	var restext;
	if(d.val1.length==0 || d.val2.length==0) {
		restext="Worker側でチェック。文字列を入力してください";
	}else{
		restext="Worker側でテキストを繋げます:"+d.val1+d.val2;
	}
postMessage(restext);
}

ワーカー側でデータを受信したときの処理

ワーカーでは、呼び出しもとのワーカーインスタンスのPostMessageメソッドが実行されると、ワーカー側のonmessageイベントが発生されます。
もちろん呼び出し元から送られてきたデータを受け取るには、こちらもイベントオブジェクトの(e)もしくは(event)などのdataプロパティから取得することが出来る。

処理が完了して、呼び出し元のワーカーインスタンスにデータを返信するにはonmessageメソッド内で、その結果をpostMessageの引数にセットして実行すると、「④ワーカー側の結果の受信した処理」の匿名関数が実行されます。