マイナー・マイナー

隠れた名作の発掘が生きがい。

Web Workersで並列処理の開始と停止を実装する


スポンサードリンク

Web Workersは並列処理を実現できるHTML5APIです。高負荷な処理をワーカーに任せることで、ブラウザ上での処理の軽減が期待できます。このAPIを用いて、並列処理の開始/停止を行うサンプルプログラムを書きました。


例えば5秒くらいかかるような重い処理をシングルスレッドで実行させると、ブラウザがフリーズしたみたいに見えます。その間に行われる操作はすぐに反応しなくなります。


ブラウザがフリーズしたみたいに見える例

<!DOCTYPE html>
<html lang="ja">
     <head>
          <meta charset="utf-8">
          <title>ただ5秒くらいかかる処理</title>
          <script type="text/javascript">
               function doSomething() {
                    // 5秒くらいかかる処理
                    var time1 = new Date().getTime();
                    var time2 = new Date().getTime();
                    while ((time2 -  time1) < 5000){
                         time2 = new Date().getTime();
                    }
                    document.getElementById("result").innerHTML = "success";
               };
          </script>
     </head>
     <body>
          <input type="button" onClick="doSomething()" value="5秒くらいかかる処理">
          <div id="result"></div>
     </body>
</html>


重い処理はスレッドに任せます。Workerオブジェクトを作成し、そこにメッセージを送信することで、並列処理が実現できます。

<!DOCTYPE html>
<html lang="ja">
     <head>
          <meta charset="utf-8">
          <title>Workerの挙動確認</title>
          <script type="text/javascript">
               var worker = new Worker("task.js");
               function startSomething() {
                    worker.onmessage = function(event) {
                         var message = event.data;
                         document.getElementById("result").innerHTML = message;
                    };
                    worker.postMessage("test");
               };
               function stopSomething() {
                    worker.terminate();
                    document.getElementById("result").innerHTML = "stop";
               };
          </script>
     </head>
     <body>
          <input type="button" onClick="startSomething()" value="5秒くらいかかる処理">
          <input type="button" onClick="stopSomething()" value="停止">
          <div id="result"></div>
     </body>
</html>


task.js

onmessage = function(event) {
     // 5秒くらいかかる処理
     var time1 = new Date().getTime();
     var time2 = new Date().getTime();
     while ((time2 -  time1) < 5000){
          time2 = new Date().getTime();
     }
    
     var result = event.data + " success";
     postMessage(result);
}


Workerオブジェクト生成時の引数にワーカースクリプト(task.js)を指定します。このワーカースクリプトに並列処理させたいコードを記述します。


Workerの利用側では、WorkerのpostMessageメソッドでワーカーにメッセージを送信します。ワーカーがメッセージを受信すると、onmessageが呼びだされます。この中で書かれた処理は、ワーカーの呼び出し側とは独立に処理されます。


Workerを終了させたいときはterminateメソッドを呼び出します。ワーカーが処理中の場合は、処理がキャンセルされます。(再度スタートさせたときは、Workerオブジェクトの再作成が必要です)