Web Workers APIを利用するとJavaScriptにおいてマルチスレッドの処理をおこなうことができます。
下記リンクは、本記事で作成したWeb Workerのサンプル画面です。「計算」ボタンをクリックすると、フォームに入力した数値までの素数の数を別スレッドにて計算します。「終了」ボタンをクリックすると、スレッドは破棄され計算は終了します。
worker.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <form> <input id="invest" type="text" size="10" value=100000 />の中に素数は <span id="result">○○○</span>個あります。 <input id="start" type="button" value="計算" /> <input id="stop" type="button" value="停止" /> </form> <script> let result = document.getElementById('result'); let worker = new Worker('worker.js'); document.getElementById('start').addEventListener('click', () => { worker.postMessage({ invest: document.getElementById('invest').value, }); }); worker.addEventListener('message', (e) => { result.textContent = e.data; }, false); document.getElementById('stop').addEventListener('click', () => { worker.terminate(); result.textContent = '<停止>'; }); worker.addEventListener('error', (e) => { console.log(e.message); }, false) </script> </body> </html> |
19行目
Workerオブジェクトを作成します。引数にはメインスレッドとは別の処理をおこなうworker.jsを指定しています。これでブラウザによるメインスレッド(UIスレッド)とworker.jsの2つのスレッドが生成されます。メイン以外のスレッドを一般的に「ワーカー」と呼びます。このワーカーによるスレッドは、ブラウザの描画とは別スレッドであるため計算中もフォームを編集することが可能です。
Chromのデベロッパーツールでもスレッドを確認できます。
22〜24行目
27〜29行目
messageイベントによって、ワーカーからの送信を検知しています。
32行目
メインスレッドにおいてワーカーを終了するにはterminate()メソッドを利用します。ワーカーの中で自身のスレッドを終了するには、close()を利用します。
worker.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
self.addEventListener('message', function (e) { let n, i, count = 0; const num = e.data.invest; for (n = 2; n <= num; n++) { for (i = 2; i < n; i++) { if (n % i == 0) break; } if (n == i) { console.log(n); count++; postMessage(count); } } }) |
1行目
messageイベントでメインスレッドからの送信を検知しています。
13行目
postMessage()メソッドでメインスレッドに対して値を返しています。
素数の求め方については下記ページをご覧下さい。
ちなみに下記リンクは、Web Workerを利用していないサンプル画面です。計算の間は画面が止まり、フォームも編集できないことを確認できます。
no-worke.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <form> <input id="invest" type="text" size="10" value=100000 />の中に素数は <span id="result"></span>個あります。 <input id="start" type="button" value="計算" /> </form> <script> document.getElementById('start').addEventListener('click', function (e) { let n, i, count = 0; const num = document.getElementById('invest').value; for (n = 2; n <= num; n++) { for (i = 2; i < n; i++) { if (n % i == 0) break; } if (n == i){ console.log(n); count++ document.getElementById('result').textContent = count; } } }); </script> </body> </html> |