WebWorker?とは  †
- HTML/Javascript は、原則的に一つのスレッドで動いていた
- setTimeout(func, 999) は、func の実行を 999 ms 後に実行するだけで、並列に動作するわけではない
- Promise なんかも並列に動作するわけではなく、ブラウザの描画スレッドの中でのイベント待ちをしている
 
- WebWorker?を使うと、Javascriptでもマルチスレッドアプリを作ることができる
- 使い方 → サンプルアプリを参照
- ★留意事項
- Workerスレッド側で、DOM にアクセスすることができない
- jQuery は使えないことに注意 ! $.get() とかは、内部的に DOM を使っている。Workerスレッド側で Ajax をしたいときには XMLHttpRequest? を生で使う必要がある
 
サンプルアプリ  †
- サンプルアプリについて
- メインスレッドで時計が動いている (500ms ごとに表示を更新している)
- ボタンを押して重い処理を動かして、CPUメータが 1Core 100% 使われていることを確認してください
- Workerを呼び出して重い処理をしても、Workerスレッドの負荷が100%になるだけなので、メインスレッドで動いている時計は止まらない
- メインスレッド内で重い処理をすると、メインスレッドの負荷が100%になるので、メインスレッドで動いている時計が止まってしまう
 
- index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
    <span id="clock"></span> <br/>
    <table border=0>
      <tr><td>Worker を起動</td><td><button id="btn1">Run</button></td></tr>
      <tr><td>通常の関数呼出</td><td><button id="btn2">Run</button></td></tr>
    </table>
<script
  src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
  integrity="sha256-3edrmyuQ0w65f8gfBsqowzjJe2iM6n0nKciPUp8y+7E="
  crossorigin="anonymous"></script>
<script>
// 時計 (メインスレッド)
function clock() {
  $('#clock').text(new Date());
  setTimeout(clock, 500);
}
clock();
// 別スレッドで重い処理を動かす
var worker = new Worker('js/worker.js');
$('#btn1').on('click', function(){
  var $btn = $(this);
  
  // 別スレッドの処理起動
  $btn.text('Processing');
  $btn.prop('disabled', true);
  worker.postMessage('start');
});
// 別スレッドの処理終了
worker.addEventListener('message', function(e) {
  console.log(e.data);
  var $btn = $('#btn1');
  $btn.text('Run');
  $btn.prop('disabled', false);
}, false);
// メインスレッドで重い処理を動かす
$('#btn2').on('click', function(){
  var $btn = $(this);
  
  // 別スレッドの処理起動
  $btn.text('Processing');
  $btn.prop('disabled', true);
  // setTimeout をかまさないと、ボタンのラベルが "Processing"
  // になる前に main thread の負荷が 100% になる
  setTimeout(function(){
    console.log('start');
    // 何かの重い処理
    for(cnt1=0; cnt1<50; cnt1++) {
    for(cnt2=0; cnt2<10000; cnt2++) {
    for(cnt3=0; cnt3<10000; cnt3++) {
    }
    }
    }
    console.log('end');
    
    // 終了後の処理
    $btn.text('Run');
    $btn.prop('disabled', false);
  },100);
});
</script>
</body>
</html>
 
- js/worker.js
self.addEventListener('message', function(e) {
  // receive objeect from main thread
  console.log(e.data);
  
  for(cnt1=0; cnt1<50; cnt1++) {
  for(cnt2=0; cnt2<10000; cnt2++) {
  for(cnt3=0; cnt3<10000; cnt3++) {
  }
  }
  }
  // send object to main thread
  self.postMessage('loop end');
  
}, false);
 
HTML