From 1c02061e0eaf23b7895e38cfbfebda00d1e0268f Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Sat, 12 Jun 2021 03:26:54 +0900 Subject: Update Web/API/Web_Workers_API/Using_web_workers (#1072) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 2021/04/30 時点の英語版に同期 - 原語併記マクロを削除 --- .../web_workers_api/using_web_workers/index.html | 465 +++++++++++---------- 1 file changed, 245 insertions(+), 220 deletions(-) (limited to 'files') diff --git a/files/ja/web/api/web_workers_api/using_web_workers/index.html b/files/ja/web/api/web_workers_api/using_web_workers/index.html index e7719ecabe..3da6e5ee2a 100644 --- a/files/ja/web/api/web_workers_api/using_web_workers/index.html +++ b/files/ja/web/api/web_workers_api/using_web_workers/index.html @@ -7,109 +7,110 @@ tags: - Guide - HTML5 - JavaScript + - WebWorkers - Workers translation_of: Web/API/Web_Workers_API/Using_web_workers ---
{{DefaultAPISidebar("Web Workers API")}}
-

Web Worker は、ウェブコンテンツがスクリプトをバックグラウンドのスレッドで実行するためのシンプルな手段です。 Worker スレッドは、ユーザーインターフェイスを妨げることなくタスクを実行できます。加えて、それらは (responseXML 属性や channel 属性は常に null ですが) XMLHttpRequest を使用して入出力を行うこともできます。生成された Worker は、生成元が指定したイベントハンドラーへメッセージを送ることにより JavaScript コードへメッセージを送ることができます (その逆も可能です)。本記事では、 Web Workers の使い方を詳しく紹介します。

+

Web Worker は、ウェブコンテンツがスクリプトをバックグラウンドのスレッドで実行するためのシンプルな手段です。ワーカースレッドは、ユーザーインターフェイスを妨げることなくタスクを実行できます。加えて、 XMLHttpRequest (responseXML 属性や channel 属性は常に null ですが) または fetch (そのような制約なし) を使用して入出力を行うこともできます。生成されたワーカーは、オリジンが指定したイベントンドラーへメッセージを送ることにより、ウィンドウript コードワーカーその逆も可能です)。本記事では、 Web Worker の使い方を詳しく紹介します。

-

Web Workers API

+

Web Worker API

-

Worker はコンストラクター (例えば {{domxref("Worker.Worker", "Worker()")}}) を使用して生成されたオブジェクトであり、名前付きの JavaScript ファイル (このファイルは Worker スレッドで実行するコードを持ちます) を実行します。また Worker は、カレントの {{domxref("window")}} とは異なるグローバルコンテキストで実行されます。従って、{{domxref("Worker")}} 内でカレントのグローバルスコープを取得するために ({{domxref("window.self","self")}} の代わりに) {{domxref("window")}} ショートカットを使用しても、エラーが返ります。

+

ワーカーはコンストラクター (例えば {{domxref("Worker.Worker", "Worker()")}}) を使用して生成されるオブジェクトであり、名前付きの JavaScript ファイル (このファイルはワーカースレッドで実行するコードを持ちます) を実行します。またワーカーは、現在の {{domxref("window")}} とは異なるグローバルコンテキストで実行されます。従って、 {{domxref("window")}} を ({{domxref("window.self","self")}} の代わりに) 使用して現在のグローバルスコープを取得しようとすると、 {{domxref("Worker")}} の中ではエラーが返されます。

-

Worker のコンテキストは、Dedicated Workers (ひとつのスクリプトが利用する、標準的な Workers) の場合は {{domxref("DedicatedWorkerGlobalScope")}} オブジェクトで表します (Shared Workers の場合は {{domxref("SharedWorkerGlobalScope")}})。Dedicated Worker は、Worker を生成したスクリプトだけがアクセスできます。一方 Shared Worker は、複数のスクリプトからアクセスできます。

+

ワーカーのコンテキストは、専用ワーカー (単一のスクリプトで利用される標準的なワーカー) の場合は {{domxref("DedicatedWorkerGlobalScope")}} オブジェクトで表されます (共有ワーカーの場合は {{domxref("SharedWorkerGlobalScope")}} です)。専用ワーカーは、最初にワーカーを起動したスクリプトだけがアクセスできます。一方、共有ワーカーは複数のスクリプトからアクセスできます。

-

メモ: Worker のリファレンスドキュメントや追加のガイドについては Web Workers API のトップページをご覧ください。

+

メモ: ワーカーのリファレンスドキュメントや追加のガイドについては Web Workers API のトップページをご覧ください。

-

Worker スレッドでは、いくつかの制限のもとでどのようなコードでも実行できます。例えば、Worker 内から直接 DOM を操作することはできません。また {{domxref("window")}} オブジェクトのデフォルトのメソッドやプロパティで、使用できないものがあります。それでも WebSocketIndexedDB、 Firefox OS 限定の Data Store API といったデータストレージ機構など、window 配下にある多数のアイテムを使用できます。詳しくは Web Worker で使用できる関数やクラス をご覧ください。

+

ワーカースレッドでは、どのようなコードでも実行できますが、いくつかの制限があります。例えば、ワーカー内から直接 DOM を操作することはできません。また {{domxref("window")}} オブジェクトの既定のメソッドやプロパティで、使用できないものがあります。それでも、window 配下にある多数のアイテム、たとえば WebSocketIndexedDB のようなデータストレージ機構などを使用できます。詳しくはワーカーで使用できる関数やクラスをご覧ください。

-

メッセージシステムを使用して、Worker とメインスレッドの間でデータを送信します。どちらも postMessage() メソッドを使用してメッセージを送信して、onmessage イベントハンドラーによってメッセージに応答します (メッセージは {{event("Message")}} イベントの data 属性に収められます)。データは共有せず、コピーします。

+

ワーカーとメインスレッドの間でデータをやり取りするには、メッセージの仕組みが使用されます。どちらも postMessage() メソッドを使用してメッセージを送信し、onmessage イベントハンドラーによってメッセージに応答します (メッセージは {{event("Message")}} イベントの data 属性に収められます)。データは共有されず、コピーされます。

-

Worker は新たな Worker を作成できます。ただし、それらの Worker が親ページとして同じ生成元のもとに存在する場合に限ります。また、Worker はネットワーク I/O のために XMLHttpRequest を使用できますが、例外として XMLHttpRequestresponseXML および channel 属性は常に null を返します。

+

ワーカーは、親ページと同じオリジン内でホスティングされている場合に限り、さらに新たなワーカーを起動することができます。また、ワーカーは XMLHttpRequest を使用してネットワーク I/O を行うことができますが、例外として XMLHttpRequestresponseXML および channel 属性は常に null を返します。

-

Dedicated Worker

+

専用ワーカー (Dedicated worker)

-

前述のとおり Dedicated Worker は、呼び出し元のスクリプトだけがアクセスできます。本章では基本的な Dedicated Worker のサンプル JavaScript を見ていきます (Dedicated Worker を実行する)。このサンプルでは、乗算を行う 2 つの数値を入力できます。数値は Dedicated Worker に送られて乗算され、そしてページに返された計算結果を表示します。

+

前述のとおり、専用ワーカーには呼び出し元のスクリプトだけがアクセスできます。この節では基本的な専用ワーカーのサンプルにある JavaScript を見ていきます (専用ワーカーを実行する)。これは、 2 つの数字を入力して掛け合わせることができるものです。数字は専用のワーカーに送られて掛け合わされ、その結果がページに戻されて表示されます。

-

これはあまり面白みのないサンプルですが、基本的な Worker のコンセプトを紹介する間はシンプルに保とうと考えています。より高度な詳細情報は、本章の後半で扱います。

+

これはあまり面白みのないサンプルですが、基本的なワーカーの概念を紹介する間はシンプルに保とうと考えています。より高度な詳細情報は、この記事の後半で扱います。

-

Worker 機能を検出する

+

ワーカー機能の検出

-

エラー制御と後方互換性を向上させるため、以下のように Worker へアクセスするコードを包み込むとよいでしょう (main.js):

+

エラー制御と後方互換性を向上させるため、ワーカーにアクセスするコードを以下のコードの中に包むといいでしょう (main.js)。

-
if (window.Worker) {
+
if (window.Worker) {
 
   ...
 
 }
-

Dedicated Worker を生成する

+

専用ワーカーの起動

-

新しい Worker は簡単に生成できます。必要なことは、Worker スレッドで実行するスクリプトの URI を指定した {{domxref("Worker.Worker", "Worker()")}} コンストラクターを呼び出すだけです (main.js):

+

新しいワーカーは簡単に生成できます。必要なことは、ワーカースレッドで実行するスクリプトの URI を指定した {{domxref("Worker.Worker", "Worker()")}} コンストラクターを呼び出すことだけです (main.js)。

-
var myWorker = new Worker('worker.js');
+
var myWorker = new Worker('worker.js');
 
-

Dedicated Worker とメッセージをやりとりする

+

専用ワーカーとメッセージをやりとりする

-

Worker のマジックは、{{domxref("Worker.postMessage", "postMessage()")}} メソッドと {{domxref("Worker.onmessage", "onmessage")}} イベントハンドラーによって実現します。Worker にメッセージを送りたいときは、以下のようにしてメッセージを送信します (main.js):

+

ワーカーのマジックは、{{domxref("Worker.postMessage", "postMessage()")}} メソッドと {{domxref("Worker.onmessage", "onmessage")}} イベントハンドラーによって実現します。ワーカーにメッセージを送りたいときは、以下のようにしてメッセージを投稿します (main.js)。

-
first.onchange = function() {
-  myWorker.postMessage([first.value,second.value]);
+
first.onchange = function() {
+  myWorker.postMessage([first.value, second.value]);
   console.log('Message posted to worker');
 }
 
 second.onchange = function() {
-  myWorker.postMessage([first.value,second.value]);
+  myWorker.postMessage([first.value, second.value]);
   console.log('Message posted to worker');
 }
-

変数 first および second で示される、2 つの {{htmlelement("input")}} 要素があります。どちらかの値が変わると、双方の値を配列として Worker へ送信するために myWorker.postMessage([first.value,second.value]) を使用します。メッセージでは、おおむねどのようなものでも送信できます。

+

2 つの {{htmlelement("input")}} 要素があり、それぞれ変数 firstsecond で表されています。どちらかの値が変化すると、 myWorker.postMessage([first.value,second.value]) を使用して、双方の値を配列としてワーカーに送信します。メッセージでは、おおむねどのようなものでも送信できます。

-

Worker では以下のようにイベントハンドラーのブロックにコードを記述すると、メッセージを受け取ったときに応答できます (worker.js):

+

ワーカー内では、以下のようにイベントハンドラーのブロックにコードを記述すると、メッセージを受け取ったときに応答できます (worker.js)。

-
onmessage = function(e) {
+
onmessage = function(e) {
   console.log('Message received from main script');
   var workerResult = 'Result: ' + (e.data[0] * e.data[1]);
   console.log('Posting message back to main script');
   postMessage(workerResult);
 }
-

onmessage ハンドラにより、メッセージを受け取ったときになんらかののコードを実行できます。メッセージ自体は、message イベントの data 属性で手に入ります。サンプルコードでは2つの数値で乗算を行った後、再び postMessage() を使用して計算結果をメインスレッドに返しています。

+

onmessage ハンドラーにより、メッセージを受け取ったときになんらかののコードを実行できます。メッセージ自体は、message イベントの data 属性で手に入ります。ここでは 2 つの数値で乗算を行った後、再び postMessage() を使用して計算結果をメインスレッドに返しています。

-

メインスレッドに戻ると再び onmessage を使用して、Worker から返されたメッセージに応答します:

+

メインスレッドに戻ると、再び onmessage を使用して、ワーカーから返されたメッセージに応答します。

-
myWorker.onmessage = function(e) {
+
myWorker.onmessage = function(e) {
   result.textContent = e.data;
   console.log('Message received from worker');
 }
-

ここではメッセージイベントからデータを取り出して、result の textContent へ格納しています。よって、ユーザは計算結果を参照できます。

+

ここではメッセージイベントからデータを取り出して、結果の段落の textContent へ格納しています。よって、ユーザーは計算結果を見ることができます。

-
メモ: メインのスクリプトスレッドで onmessage および postMessage() を使用するときは Worker オブジェクトに付随させなければなりませんが、 Worker 内ではそのようにする必要はありません。これは、 Worker 内ではそれ自身が実質的にグローバルスコープであるためです。
+
: メインのスクリプトスレッドで onmessage および postMessage() を使用するときは Worker オブジェクトにぶら下げなければなりませんが、ワーカー内ではそのようにする必要はありません。これは、ワーカー内ではそれ自身が実質的にグローバルスコープであるためです。
-
メモ: メッセージをメインスレッドと Worker の間でやりとりするとき、メッセージは共有せずに "伝送" (移動) します。詳しい解説は、{{anch("Transferring data to and from workers further details", "Worker との間のデータ転送: 詳細")}}をご覧ください。
+
: メッセージをメインスレッドとワーカーの間でやりとりするとき、共有されるのではなく、コピーまたは「転送」 (移動) されます。詳しい解説は、{{anch("Transferring data to and from workers further details", "ワーカーとの間のデータ転送の詳細")}}をご覧ください。
-

Worker の終了

+

ワーカーの終了

-

実行中の Worker を直ちに終了したい場合は、 Worker の terminate() メソッドを呼び出してください。

+

メインスレッドから実行しているワーカーを直ちに終了させる必要がある場合は、ワーカーの {{domxref("Worker", "terminate")}} メソッドを呼び出してください。

-
myWorker.terminate();
+
myWorker.terminate();
-

Worker スレッドは直ちに終了します。

+

ワーカースレッドは直ちに終了します。

-

エラーハンドリング

+

エラー処理

-

Worker で実行時エラーが発生すると、 onerror イベントハンドラーが呼び出されます。これは、 ErrorEvent インターフェイスを実装している error イベントを受け取ります。

+

ワーカー内で実行時エラーが発生すると、 onerror イベントハンドラーが呼び出されます。これは error という名前のイベントを受け取りますが、これは ErrorEvent インターフェイスを実装しています。

-

イベントはバブリングせず、またキャンセルすることができます。 Worker はエラーイベントの {{domxref("Event/preventDefault", "preventDefault()")}} メソッドを呼び出すことで、発生元の既定のアクションを抑制することができます。

+

イベントはバブリングせず、またキャンセルすることができます。ワーカーはエラーイベントの preventDefault() メソッドを呼び出すことで、発生元の既定のアクションを抑制することができます。

-

エラーイベントには、以下の重要な 3 つの項目があります。

+

エラーイベントには、以下の重要な 3 つのフィールドがあります。

message
@@ -120,56 +121,56 @@ second.onchange = function() {
スクリプトファイル内でエラーが発生した場所の行番号です。
-

サブ Worker の生成

+

サブワーカーの起動

-

必要であれば、 Worker がさらに Worker を生成することができます。いわゆるサブ Worker は、親ページと同じ生成元で提供しなければなりません。またサブ Worker 用の URI は、その所有ページではなく親 Worker の場所からの相対位置として分析されます。これは、 Worker の依存関係を追跡し続けることを容易にします。

+

ワーカーは、必要に応じてさらに多くのワーカーを生み出すことができます。いわゆるサブワーカーは、親ページと同じオリジン内でホストされていなければなりません。また、サブワーカーの URI は、親ページのものではなく、親ワーカーの位置を基準に解決されます。これにより、ワーカーは自分の依存関係がどこにあるかを簡単に把握することができます。

-

スクリプトやライブラリのインポート

+

スクリプトやライブラリーのインポート

-

Worker スレッドはグローバル関数や、スクリプトをインポートするための importScripts() にアクセスできます。これはインポートするリソースの URI を 0 個以上、引数として受け入れます。以下のサンプルはすべて有効です。

+

Worker スレッドはグローバル関数や、スクリプトをインポートするための importScripts() にアクセスできます。これはインポートするリソースの URI を 0 個以上、引数として受け入れます。以下の例はすべて有効です。

-
importScripts();                         /* 何もインポートしない */
+
importScripts();                         /* 何もインポートしない */
 importScripts('foo.js');                 /* "foo.js" をインポート */
 importScripts('foo.js', 'bar.js');       /* 2 つのスクリプトをインポート */
 importScripts('//example.com/hello.js'); /* 他のオリジンのスクリプトをインポートすることができる */
-

ブラウザーはそれぞれのスクリプトを読み込み、実行します。 Worker は各スクリプトのグローバルオブジェクトを使用できます。スクリプトを読み込むことができない場合は NETWORK_ERROR を発生させて、それ以降のコードを実行しません。それでも、すでに実行されたコード ({{domxref("window.setTimeout()")}} で繰り延べされているコードを含みます) は動作します。importScripts() メソッドより後方にある関数の宣言は、常にコードの残りの部分より先に評価されることから、同様に保持されます。

+

ブラウザーはそれぞれのスクリプトを読み込み、実行します。ワーカーは各スクリプトのグローバルオブジェクトを使用できます。スクリプトを読み込むことができない場合は NETWORK_ERROR を発生させて、それ以降のコードを実行しません。それでも、すでに実行されたコード ({{domxref("WindowOrWorkerGlobalScope.setTimeout")}} で繰り延べされているコードを含みます) は動作します。importScripts() メソッドより後方にある関数の宣言は、常にコードの残りの部分より先に評価されることから、同様に保持されます。

-
注記: スクリプトは順不同にダウンロードされますが、実行は importScripts() に渡したファイル名の順に行います。これは同期的に行われます。すべてのスクリプトの読み込みと実行が行われるまで importScripts() から戻りません。
+
: スクリプトは順不同にダウンロードされることがありますが、実行は importScripts() に渡したファイル名の順に行います。これは同期的に行われます。すべてのスクリプトの読み込みと実行が行われるまで importScripts() から戻りません。
-

Shared Worker

+

共有ワーカー

-

Shared Worker は、生成元が同一であれば (異なる window、iframe、Worker からであっても) 複数のスクリプトからアクセスできます。本章では基本的な Shared Worker のサンプル JavaScript を見ていきます (Shared Worker を実行する)。こちらは Dedicated Worker のサンプルと似ていますが、2 つの数値で乗算を行うスクリプトと数値を 2 乗するスクリプトという、別々のスクリプトファイルが扱う 2 つの関数を使用できる点が異なります。どちらのスクリプトも同じ Worker を使用して、実際に必要な計算を行います。

+

共有ワーカーは、オリジンが同一であれば (異なるウィンドウ、iframe、ワーカーからであっても) 複数のスクリプトからアクセスできます。本章では基本的な共有ワーカーの例 の JavaScript を見ていきます (共有ワーカーを実行する)。こちらは専用ワーカーのサンプルと似ていますが、2 つの数値で乗算を行うスクリプトと数値を 2 乗するスクリプトという、別々のスクリプトファイルが扱う 2 つの関数を使用できる点が異なります。どちらのスクリプトも同じワーカーを使用して、実際に必要な計算を行います。

-

ここでは、 Dedicated Worker と Shared Worker の違いについて注目します。このサンプルでは 2 つの HTML ページがあり、それぞれの JavaScript は同じひとつの Worker ファイルを使用するようになっています。

+

ここでは、 専用ワーカーと共有ワーカーの違いについて注目します。この例では 2 つの HTML ページがあり、それぞれの JavaScript は同じ単一のワーカーファイルを使用するようになっています。

-

メモ: SharedWorker が複数の閲覧コンテキストからアクセスできる場合、すべての閲覧コンテキストはまったく同じオリジン (プロトコル、ホスト、ポート番号が同じ) です。

+

: 共有ワーカーが複数の閲覧コンテキストからアクセスできる場合、すべての閲覧コンテキストはまったく同じオリジン (プロトコル、ホスト、ポート番号が同じ) になります。

-

メモ: Firefox では、 Shared Worker はプライベートウィンドウとそれ以外に読み込まれた文書間で共有することができません ({{bug(1177621)}})。

+

メモ: Firefox では、共有ワーカーはプライベートウィンドウとそれ以外に読み込まれた文書間で共有することができません ({{bug(1177621)}})。

-

Shared Worker の生成

+

共有ワーカーの生成

-

新しい Shared Worker の生成方法は Dedicated Worker の場合とほとんど同じですが、コンストラクター名が異なります (index.html および index2.html をご覧ください)。それぞれのページで、以下のようなコードを使用して Worker を立ち上げます。

+

新しい共有ワーカーの生成方法は 専用ワーカー の場合とほとんど同じですが、コンストラクター名が異なります (index.html および index2.html をご覧ください)。それぞれのページで、以下のようなコードを使用してワーカーを立ち上げます。

-
var myWorker = new SharedWorker('worker.js');
+
var myWorker = new SharedWorker('worker.js');
-

Shared Worker の大きな違いのひとつが、 port オブジェクトを通して通信しなければならないことです。スクリプトが Worker と通信するために使用できる、明示的なポートが開きます (これは、 Dedicated Worker でも暗黙的に開いています)。

+

共有ワーカーの大きな違いのひとつが、 port オブジェクトを通して通信しなければならないことです。スクリプトがワーカーと通信するために使用できる、明示的なポートが開きます (これは、 専用ワーカーでも暗黙的に開いています)。

-

ポートへの接続は onmessage イベントハンドラーを使用して暗黙的に行うか、あるいはメッセージを送信する前に start() メソッドを使用して明示的に開始するかしなければなりません。 start() の呼び出しは、addEventListener() メソッドで message イベントを拾い上げる場合にのみ必要です。

+

ポートへの接続は、メッセージを送信する前に onmessage イベントハンドラーを使用して暗黙的に行うか、あるいは start() メソッドを使用して明示的に開始するかしなければなりません。 start() の呼び出しは、addEventListener() メソッドで message イベントを拾い上げる場合にのみ必要です。

-

ポート接続を開始するために start() メソッドを使用するとき、双方向の通信が必要である場合は親スレッドと Worker の両方で呼び出さなければなりません。

+

ポート接続を開始するために start() メソッドを使用するとき、双方向の通信が必要である場合は親スレッドとワーカーの両方で呼び出さなければなりません。

-

Shared Worker とのメッセージのやりとり

+

共有ワーカーとのメッセージのやりとり

-

前述のとおり Worker にメッセージを送信できるようになりましたが、postMessage() メソッドは port オブジェクトを通して呼び出さなければなりません (繰り返しますが、同様の構造が multiply.js および square.js に存在します)。

+

前述のとおりワーカーにメッセージを送信できるようになりましたが、postMessage() メソッドは port オブジェクトを通して呼び出さなければなりません (繰り返しますが、同様の構造が multiply.js および square.js に存在します)。

-
squareNumber.onchange = function() {
+
squareNumber.onchange = function() {
   myWorker.port.postMessage([squareNumber.value,squareNumber.value]);
   console.log('Message posted to worker');
 }
@@ -185,46 +186,46 @@ importScripts('//example.com/hello.js'); /* 他のオリジンのスクリプト } }
-

始めに、ポートへの接続が発生したとき (すなわち、親スレッドで onmessage イベントをセットアップしたときや親スレッドで start() メソッドを明示的に呼び出したとき) にコードを実行するため onconnect ハンドラを使用します。

+

始めに、ポートへの接続が発生したとき (すなわち、親スレッドで onmessage イベントをセットアップしたときや親スレッドで start() メソッドを明示的に呼び出したとき) にコードを実行するため onconnect ハンドラーを使用します。

イベントオブジェクトの ports 属性を使用してポートを取り出し、変数に格納します。

-

次に、計算を実行して結果をメインスレッドに返すため、ポートの onmessage ハンドラを使用します。Worker スレッドで onmessage ハンドラをセットアップすると、親スレッドに戻すポート接続を暗黙的に開きます。従って、実際は前述のとおり port.start() を呼び出す必要はありません。

+

次に、計算を実行して結果をメインスレッドに返すため、ポートの message のハンドラーを使用します。ワーカースレッドで message のハンドラーをセットアップすると、親スレッドに戻すポート接続を暗黙的に開きます。従って、実際は前述のとおり port.start() を呼び出す必要はありません。

最後に、メインスレッドに戻ってメッセージを扱います (繰り返しますが、同様の構造が multiply.js および square.js に存在します)。

-
myWorker.port.onmessage = function(e) {
+
myWorker.port.onmessage = function(e) {
   result2.textContent = e.data;
   console.log('Message received from worker');
 }
-

ポートを通して Worker からメッセージが戻ったときは、結果のデータ型を確認してから適切なパラグラフに計算結果を挿入します。

+

ポートを通してワーカーからメッセージが戻ったときは、結果のデータ型を確認してから適切な段落に計算結果を挿入します。

-

スレッドセーフについて

+

スレッドセーフについて

-

{{domxref("Worker")}} インターフェイスは実際の OS レベルのスレッドを生成しますので注意深いプログラマは、気をつけなければ同時実行によって、コードにおいて "興味深い" 効果を引き起こす可能性があると懸念するかもしれません。

+

{{domxref("Worker")}} インターフェイスでは、OS レベルの実際のスレッドが生成されるため、注意深いプログラマーは、注意しないと同時実行によってコードに「面白い」効果が生じるのではないかと懸念するかもしれません。

-

しかし Web Worker は他のスレッドとの通信ポイントが注意深く制御されていますので、実際は同時実行による問題を引き起こすことが非常に困難です。スレッドセーフではないコンポーネントや DOM にはアクセスできません。また、スレッド内外のデータはシリアライズしたオブジェクトを通して渡さなければなりません。よって、コードで問題を起こすことはとても難しいのです。

+

しかし、 Web Worker は他のスレッドとの通信ポイントが慎重に制御されているため、同時実行の問題を引き起こすことは実際には非常に困難です。スレッドセーフでないコンポーネントや DOM にはアクセスできません。また、シリアル化されたオブジェクトを通して特定のデータをスレッドに出し入れしなければなりません。ですから、コードで問題を起こすためには、かなり難しいのです。

-

コンテンツセキュリティポリシー

+

コンテンツセキュリティポリシー

-

Worker は、自分を生成した文書から区別された独自の実行コンテキストを持っているとみなされます。このため、一般に、自分を生成した文書 (または親 Worker) のコンテンツセキュリティポリシーでは管理されません。そのため例えば、文書が次のヘッダー付きで読み込まれたと仮定します。

+

ワーカーは、自分を生成した文書から区別された独自の実行コンテキストを持っているとみなされます。このため、一般に、自分を生成した文書 (または親ワーカー) のコンテンツセキュリティポリシーでは管理されません。そのため例えば、文書が次のヘッダー付きで読み込まれたと仮定します。

-
Content-Security-Policy: script-src 'self'
+
Content-Security-Policy: script-src 'self'
-

特に、これは {{jsxref("Global_Objects/eval", "eval()")}} を使用したスクリプトを防ぎます。しかし、スクリプトが Worker を構築した場合、 Worker のコンテキストで実行中のコードは eval() を使用することができます。
-
- Worker のコンテンツセキュリティポリシーを指定するには、 Worker スクリプト自身が配信されたリクエストの Content-Security-Policy レスポンスヘッダーで設定してください。
-
- Worker スクリプトのオリジンがグローバルに一意な識別子である場合 (例えば、 URL が data や blob のスキームであった場合) は例外です。この場合、 Worker は文書の CSP またはそれを作成した Worker を継承します。

+

特に、これは eval() を使用したスクリプトを防ぎます。しかし、スクリプトがワーカーを構築した場合、ワーカーのコンテキストで実行中のコードは eval() を使用することができます。

-

Worker とのデータ伝送の詳細

+

ワーカーのコンテンツセキュリティポリシーを指定するには、ワーカースクリプト自身が配信されたリクエストの Content-Security-Policy レスポンスヘッダーで設定してください。

-

メインページと Worker との間で送られるメッセージは、共有されるのではなくコピーされます。オブジェクトは Worker に渡している間シリアライズされ、その後戻されたときにシリアライズが解除されます。ページと Worker は同一のインスタンスを共有しませんので、結果として双方に複製が作られます。ほとんどのブラウザーはこの機能を structured cloning として実装しています。

+

ワーカースクリプトのオリジンがグローバルに一意な識別子である場合 (例えば、 URL のスキームが data や blob であった場合) は例外です。この場合、ワーカーは文書の CSP またはそれを作成したワーカーを継承します。

-

これを説明するため、 worker からメインページおよびその逆の移動において共有されず複製される値の動作をシミュレーションする、教育的な用途の関数 emulateMessage() を作成しましょう:

+

ワーカーとのデータ転送の詳細

-
function emulateMessage(vVal) {
+

メインページとワーカーの間で渡されるデータは、共有ではなくコピーされます。オブジェクトは、ワーカーに渡されるときにシリアライズされ、その後、反対側でシリアライズが解除されます。ページとワーカーは同じインスタンスを共有しないため、最終的には両側に複製が作成されます。ほとんどのブラウザーはこの機能を構造化複製として実装しています。

+ +

これを説明するため、教育的な用途の関数 emulateMessage() を作成し、 worker からメインページおよびその逆の移動において共有されず複製される値の動作をシミュレーションしてみましょう。

+ +
function emulateMessage(vVal) {
     return eval('(' + JSON.stringify(vVal) + ')');
 }
 
@@ -262,11 +263,11 @@ var example5 = new Animal('Cat', 3);
 alert(example5.constructor); // Animal
 alert(emulateMessage(example5).constructor); // Object
-

共有されず複製される値をメッセージと呼びます。おわかりかと思いますがメッセージpostMessage() を使用してメインスレッドへ、またはメインスレッドから送信でき、また message イベントの {{domxref("MessageEvent.data", "data")}} 属性に、Worker から返されたデータが含まれます。

+

複製され、共有されない値をメッセージと呼びます。もうお分かりだと思いますが、メッセージpostMessage() を使ってメインスレッドとの間で送受信することができ、 message イベントの {{domxref("MessageEvent.data", "data")}} 属性には、ワーカーから返されたデータが含まれています。

-

example.html (メインページ)

+

example.html (メインページ)

-
var myWorker = new Worker('my_task.js');
+
var myWorker = new Worker('my_task.js');
 
 myWorker.onmessage = function(oEvent) {
   console.log('Worker said : ' + oEvent.data);
@@ -274,123 +275,123 @@ myWorker.onmessage = function(oEvent) {
 
 myWorker.postMessage('ali');
-

my_task.js (Worker)

+

my_task.js (ワーカー)

-
postMessage("I\'m working before postMessage(\'ali\').");
+
postMessage("I\'m working before postMessage(\'ali\').");
 
 onmessage = function(oEvent) {
   postMessage('Hi ' + oEvent.data);
 };
-

structured cloning アルゴリズムは JSON や、循環参照など JSON ではできないいくつかのものを受け入れることができます。

+

構造化複製アルゴリズムは JSON を受け入れることができ、循環参照など JSON ではできないものもいくつか受け入れることができます。

-

データ引き渡しのサンプル

+

データ引き渡しの例

-

例 #1: 高度な JSON データ渡しと切り替えシステムの作成

+

例 #1: 高度な JSON データ渡しと切り替えシステムの作成

-

もしいくつかの複雑なデータを渡さなければならず、メインページとWorkerの両方で多くの異なる関数を呼び出さなければならない場合、すべてをまとめてグループにするシステムを作ることができます。

+

もしいくつかの複雑なデータを渡さなければならず、メインページとワーカーの両方で多くの異なる関数を呼び出さなければならない場合、すべてをまとめてグループにするシステムを作ることができます。

-

はじめに、WorkerのURL、デフォルトのリスナー、エラーハンドラーを持つQueryableWorkerクラスを作ります。このクラスはリスナーのリストを記録し、Workerとのコミュニケーションに役立ちます。

+

はじめに、ワーカーの URL、既定のリスナー、エラーハンドラーを持つ QueryableWorker クラスを作ります。このクラスはリスナーのリストを記録し、ワーカーとのコミュニケーションに役立てます。

-
function QueryableWorker(url, defaultListener, onError) {
-    var instance = this,
-        worker = new Worker(url),
-        listeners = {};
+
function QueryableWorker(url, defaultListener, onError) {
+    var instance = this,
+        worker = new Worker(url),
+        listeners = {};
 
-    this.defaultListener = defaultListener || function() {};
+    this.defaultListener = defaultListener || function() {};
 
-    if (onError) {worker.onerror = onError;}
+    if (onError) {worker.onerror = onError;}
 
-    this.postMessage = function(message) {
-        worker.postMessage(message);
-    }
+    this.postMessage = function(message) {
+        worker.postMessage(message);
+    }
 
-    this.terminate = function() {
-        worker.terminate();
+    this.terminate = function() {
+        worker.terminate();
     }
 }
-

そして、リスナーを追加 / 削除する方法を追加します。

+

そして、リスナーを追加/削除する方法を追加します。

-
this.addListeners = function(name, listener) {
-    listeners[name] = listener;
+
this.addListeners = function(name, listener) {
+    listeners[name] = listener;
 }
 
 this.removeListeners = function(name) {
     delete listeners[name];
 }
-

ここでは、説明のためにWorkerに 2つの簡単な操作をさせてみましょう。2つの数値の差を取得することと、3秒後にアラートを出すことです。これを実現するために、まず最初にsendQueryメソッドを実装します。これは、Workerが実際に対応するメソッドを持っているかどうかを問い合わせるものです。

+

ここでは、説明のためにワーカーに 2 つの簡単な操作をさせてみましょう。 2 つの数値の差を取得することと、 3 秒後にアラートを出すことです。これを実現するために、まず最初に sendQuery メソッドを実装します。これは、ワーカーが実際に対応するメソッドを持っているかどうかを問い合わせるものです。

-
/*
-  This functions takes at least one argument, the method name we want to query.
-  Then we can pass in the arguments that the method needs.
+
/*
+  This functions takes at least one argument, the method name we want to query.
+  Then we can pass in the arguments that the method needs.
  */
 this.sendQuery = function() {
     if (arguments.length < 1) {
-         throw new TypeError('QueryableWorker.sendQuery takes at least one argument');
-         return;
-    }
-    worker.postMessage({
-        'queryMethod': arguments[0],
-        'queryArguments': Array.prototype.slice.call(arguments, 1)
-    });
+         throw new TypeError('QueryableWorker.sendQuery takes at least one argument');
+         return;
+    }
+    worker.postMessage({
+        'queryMethod': arguments[0],
+        'queryArguments': Array.prototype.slice.call(arguments, 1)
+    });
 }
-

QueryableWorkerはonmessageメソッドで終了します。ワーカーがクエリに対応するメソッドを持っている場合、対応するリスナーの名前と必要な引数を返すはずです。

+

QueryableWorkeronmessage メソッドで終了させます。問い合わせたメソッドに対応するワーカーがあれば、対応するリスナーの名前と必要な引数を返してくれるはずなので、あとは listeners の中を探すだけです。

-
worker.onmessage = function(event) {
+
worker.onmessage = function(event) {
     if (event.data instanceof Object &&
-        event.data.hasOwnProperty('queryMethodListener') &&
-        event.data.hasOwnProperty('queryMethodArguments')) {
-        listeners[event.data.queryMethodListener].apply(instance, event.data.queryMethodArguments);
+        event.data.hasOwnProperty('queryMethodListener') &&
+        event.data.hasOwnProperty('queryMethodArguments')) {
+        listeners[event.data.queryMethodListener].apply(instance, event.data.queryMethodArguments);
     } else {
-        this.defaultListener.call(instance, event.data);
-    }
+        this.defaultListener.call(instance, event.data);
+    }
 }
 
-

それではWorkerに移りましょう。まず、2つの単純な操作を処理するためのメソッドを用意する必要があります。

+

次にワーカーです。まず、 2 つの簡単な操作を行うためのメソッドが必要です。

-
var queryableFunctions = {
+
var queryableFunctions = {
     getDifference: function(a, b) {
-        reply('printStuff', a - b);
-    },
-    waitSomeTime: function() {
-        setTimeout(function() {
-            reply('doAlert', 3, 'seconds');
-        }, 3000);
-    }
+        reply('printStuff', a - b);
+    },
+    waitSomeTime: function() {
+        setTimeout(function() {
+            reply('doAlert', 3, 'seconds');
+        }, 3000);
+    }
 }
 
 function reply() {
     if (arguments.length < 1) {
-        throw new TypeError('reply - takes at least one argument');
-        return;
-    }
-    postMessage({
-        queryMethodListener: arguments[0],
-        queryMethodArguments: Array.prototype.slice.call(arguments, 1)
-    });
+        throw new TypeError('reply - takes at least one argument');
+        return;
+    }
+    postMessage({
+        queryMethodListener: arguments[0],
+        queryMethodArguments: Array.prototype.slice.call(arguments, 1)
+    });
 }
 
 /* This method is called when main page calls QueryWorker's postMessage method directly*/
 function defaultReply(message) {
-    // do something
+    // do something
 }
 

そして、onmessageメソッドは簡単になりました。

-
onmessage = function(event) {
-    if (event.data instanceof Object &&
-        event.data.hasOwnProperty('queryMethod') &&
-        event.data.hasOwnProperty('queryMethodArguments')) {
-        queryableFunctions[event.data.queryMethod]
-            .apply(self, event.data.queryMethodArguments);
-    } else {
-        defaultReply(event.data);
-    }
+
onmessage = function(event) {
+    if (event.data instanceof Object &&
+        event.data.hasOwnProperty('queryMethod') &&
+        event.data.hasOwnProperty('queryMethodArguments')) {
+        queryableFunctions[event.data.queryMethod]
+            .apply(self, event.data.queryMethodArguments);
+    } else {
+        defaultReply(event.data);
+    }
 }
 
@@ -398,7 +399,7 @@ function defaultReply(message) {

example.html (メインページ)

-
<!doctype html>
+
<!doctype html>
   <html>
     <head>
       <meta charset="UTF-8"  />
@@ -415,31 +416,31 @@ function defaultReply(message) {
         * defaultListener: the default listener executed only when the Worker calls the postMessage() function directly
      */
     function QueryableWorker(url, defaultListener, onError) {
-      var instance = this,
-      worker = new Worker(url),
-      listeners = {};
+      var instance = this,
+      worker = new Worker(url),
+      listeners = {};
 
-      this.defaultListener = defaultListener || function() {};
+      this.defaultListener = defaultListener || function() {};
 
-      if (onError) {worker.onerror = onError;}
+      if (onError) {worker.onerror = onError;}
 
-      this.postMessage = function(message) {
-        worker.postMessage(message);
-      }
+      this.postMessage = function(message) {
+        worker.postMessage(message);
+      }
 
-      this.terminate = function() {
-        worker.terminate();
+      this.terminate = function() {
+        worker.terminate();
       }
 
-      this.addListener = function(name, listener) {
-        listeners[name] = listener;
-      }
+      this.addListener = function(name, listener) {
+        listeners[name] = listener;
+      }
 
-      this.removeListener = function(name) {
-        delete listeners[name];
+      this.removeListener = function(name) {
+        delete listeners[name];
       }
 
-      /*
+      /*
         This functions takes at least one argument, the method name we want to query.
         Then we can pass in the arguments that the method needs.
       */
@@ -454,16 +455,16 @@ function defaultReply(message) {
         });
       }
 
-      worker.onmessage = function(event) {
+      worker.onmessage = function(event) {
         if (event.data instanceof Object &&
-          event.data.hasOwnProperty('queryMethodListener') &&
-          event.data.hasOwnProperty('queryMethodArguments')) {
-          listeners[event.data.queryMethodListener].apply(instance, event.data.queryMethodArguments);
+          event.data.hasOwnProperty('queryMethodListener') &&
+          event.data.hasOwnProperty('queryMethodArguments')) {
+          listeners[event.data.queryMethodListener].apply(instance, event.data.queryMethodArguments);
         } else {
-          this.defaultListener.call(instance, event.data);
-        }
+          this.defaultListener.call(instance, event.data);
+        }
       }
-    }
+    }
 
     // 独自の「照会可能な」 worker
     var myTask = new QueryableWorker('my_task.js');
@@ -487,10 +488,10 @@ function defaultReply(message) {
 </body>
 </html>
-

my_task.js (Worker)

+

my_task.js (ワーカー)

-
var queryableFunctions = {
-  // 例 #1: 2 つの値の差を得る:
+
var queryableFunctions = {
+  // 例 #1: 2 つの値の差を得る
   getDifference: function(nMinuend, nSubtrahend) {
       reply('printStuff', nMinuend - nSubtrahend);
   },
@@ -520,14 +521,14 @@ onmessage = function(oEvent) {
   }
 };
-

各メインページ→Worker、Worker→メインページのメッセージの内容を切り替えることができます。そして、プロパティ名「queryMethod」「queryMethodListeners」「queryMethodArguments」は、QueryableWorkerとWorkerで一致していれば何でも構いません。

+

各メインページ→ワーカー、ワーカー→メインページとメッセージの内容を切り替えることができます。そして、 "queryMethod", "queryMethodListeners", "queryMethodArguments" の各プロパティ名は、 QueryableWorker とワーカーで一致していれば何でも構いません。

-

所有権の譲渡 (Transferable Objects) によるデータの引き渡し

+

所有権の譲渡によるデータの引き渡し (transferable オブジェクト)

-

Google Chrome 17 以降および Firefox 18 以降には、特定の種類のオブジェクト ({{domxref("Transferable")}} インターフェイスを実装するオブジェクトである Transferable Object) を高いパフォーマンスで Worker から、または Worker へ渡すための、追加の手段があります。Transferable Object はあるコンテキストから別のコンテキストへ、コピー操作なしに転送されます。これにより、大量のデータセットを送信する際のパフォーマンスが大きく向上します。C/C++ の経験者であれば、参照渡しと考えてください。しかし参照渡しとは異なり、転送されると元のコンテキストからその版が失われます。そしてその所有権は新しいコンテキストに譲渡されます。例えば {{domxref("ArrayBuffer")}} をメインアプリから Worker スクリプトへ転送するとき、元の {{domxref("ArrayBuffer")}} はクリアされて使用できなくなります。その内容物は (文字どおり) Worker コンテキストに{{原語併記("転送", "transfer")}}されます。

+

Google Chrome 17 以降および Firefox 18 以降には、特定の種類のオブジェクト (transferable オブジェクト、つまり {{domxref("Transferable")}} インターフェイスを実装したオブジェクト) をワーカーとの間で高いパフォーマンスで受け渡すための別な方法があります。 Transferable オブジェクトは、あるコンテキストから別のコンテキストへコピー操作なしで転送されるため、大規模なデータセットを送信する際のパフォーマンスが大幅に向上します。 C/C++ の世界から来た人は、参照渡しと考えてください。ただし、参照渡しとは異なり、呼び出し元のコンテキストの「バージョン」は転送されると利用できなくなります。その所有権は新しいコンテキストに移されます。例えば、 {{jsxref("ArrayBuffer")}} をメインアプリからワーカースクリプトに転送した場合、元の {{jsxref("ArrayBuffer")}} はクリアされ、使用できなくなります。その内容は (文字通り) ワーカーコンテキストに転送 (transfer) されます。

-
// 32MB の "file" を作成して埋めます。
-var uInt8Array = new Uint8Array(1024*1024*32); // 32MB
+
// 32MB の "file" を作成して埋めます。
+var uInt8Array = new Uint8Array(1024 * 1024 * 32); // 32MB
 for (var i = 0; i < uInt8Array.length; ++i) {
   uInt8Array[i] = i;
 }
@@ -536,14 +537,14 @@ worker.postMessage(uInt8Array.buffer, [uInt8Array.buffer]);
 
-

注記: Transferable Object、パフォーマンス、およびメソッドの機能検出について詳しくは、HTML5 Rocks の Transferable Objects: Lightning Fast! をご覧ください。

+

: Transferable オブジェクト、パフォーマンス、メソッドの機能検出について詳しくは、HTML5 Rocks の Transferable Objects: Lightning Fast! をご覧ください。

-

埋め込み Worker

+

埋め込みワーカー

-

通常のスクリプトを {{HTMLElement("script")}} 要素で埋め込むように、 Worker のコードをウェブページに埋め込むための "公式な" 方法はありません。しかし src 属性を持たず、また実行可能な MIME タイプを示さない type 属性を持つ {{HTMLElement("script")}} 要素は、JavaScript が使用できるデータブロック要素であると判断されます。"データブロック" はほとんどのテキストデータを持つことができる、HTML5 の一般的な機能です。よって、以下の方法で Worker を埋め込むことができます:

+

ワーカーのコードをウェブページに埋め込むための、通常のスクリプトを {{HTMLElement("script")}} 要素で埋め込むような「公式な}方法はありません。しかし、 {{HTMLElement("script")}} 要素が src 属性を持たず、また type 属性が実行可能な MIME タイプを示していない場合は、 JavaScript が使用できるデータブロック要素であると判断されます。「データブロック」はほとんどのテキストデータを持つことができる、 HTML5 の一般的な機能です。よって、以下の方法でワーカーを埋め込むことができます。

-
<!DOCTYPE html>
+
<!DOCTYPE html>
 <html>
 <head>
 <meta charset="UTF-8" />
@@ -551,12 +552,12 @@ worker.postMessage(uInt8Array.buffer, [uInt8Array.buffer]);
 <script type="text/js-worker">
   // MIME タイプが text/js-worker であるため、このスクリプトは JS エンジンに解釈されません。
   var myVar = 'Hello World!';
-  // worker の残りのコードをここに置きます。
+  // ワーカーの残りのコードをここに置きます。
 </script>
 <script type="text/javascript">
   // MIME タイプが text/javascript であるため、このスクリプトは JS エンジンに解釈されます。
   function pageLog(sMsg) {
-    // fragment を使用: ブラウザーは 1 回だけレンダリング/リフローします。
+    // ブラウザーがレンダリングや再フローを行うのを 1 回だけにするために fragment を使用します。
     var oFragm = document.createDocumentFragment();
     oFragm.appendChild(document.createTextNode(sMsg));
     oFragm.appendChild(document.createElement('br'));
@@ -568,14 +569,14 @@ worker.postMessage(uInt8Array.buffer, [uInt8Array.buffer]);
   onmessage = function(oEvent) {
     postMessage(myVar);
   };
-  // worker の残りのコードをここに置きます。
+  // ワーカーの残りのコードをここに置きます。
 </script>
 <script type="text/javascript">
   // MIME タイプが text/javascript であるため、このスクリプトは JS エンジンに解釈されます。
 
   //
   // 以前は blob を構築していましたが、
-  // 現在は Blob を使用します:
+  // 現在は Blob を使用します。
   var blob = new Blob(Array.prototype.map.call(document.querySelectorAll('script[type=\'text\/js-worker\']'), function (oScript) { return oScript.textContent; }),{type: 'text/javascript'});
 
   // すべての "text/js-worker" スクリプトを含む、新たな document.worker プロパティを生成します。
@@ -585,35 +586,35 @@ worker.postMessage(uInt8Array.buffer, [uInt8Array.buffer]);
     pageLog('Received: ' + oEvent.data);
   };
 
-  // Worker を開始します。
+  // ワーカーを起動します。
   window.onload = function() { document.worker.postMessage(''); };
 </script>
 </head>
 <body><div id="logDisplay"></div></body>
 </html>
-

埋め込み Worker が、新たな独自の document.worker プロパティの入れ子になります。

+

埋め込みワーカーは、新たな document.worker カスタムプロパティの中に入りました。

言うまでもなく、次の例のように、関数を Blob に変換して、その blob からオブジェクトの URL を生成することができます。

-
function fn2workerURL(fn) {
-  var blob = new Blob(['('+fn.toString()+')()'], {type: 'application/javascript'})
+
function fn2workerURL(fn) {
+  var blob = new Blob(['('+fn.toString()+')()'], {type: 'text/javascript'})
   return URL.createObjectURL(blob)
 }
-

追加サンプル

+

追加の例

-

ここでは Web Worker の使用方法について、さらにサンプルを示します。

+

ここでは Web Worker の使用方法について、さらに例を示します。

-

バックグラウンドで演算を行う

+

バックグラウンドで演算を行う

-

Worker は主に、ユーザーインターフェイスのスレッドを妨げずに CPU 負荷が大きい演算を実行するために役立ちます。このサンプルでは、 Worker をフィボナッチ数の計算に使用します。

+

ワーカーは主に、ユーザーインターフェイスのスレッドを妨げずに CPU 負荷が大きい演算を実行するために役立ちます。このサンプルでは、ワーカーをフィボナッチ数の計算に使用します。

-

JavaScript コード

+

JavaScript コード

-

以下の JavaScript コードはファイル "fibonacci.js" に保存され、次章の HTML が参照します。

+

以下の JavaScript コードをファイル "fibonacci.js" に保存し、次節の HTML から参照します。

-
var results = [];
+
var results = [];
 
 function resultReceiver(event) {
   results.push(parseInt(event.data));
@@ -642,11 +643,11 @@ onmessage = function(event) {
   }
  };
-

Worker は、Worker オブジェクトの postMessage() が呼び出されたときにメッセージを受け取る関数を onmessage プロパティに設定します (これは onmessage という名前のグローバル変数関数を定義することとは違いますので注意してください。var onmessagefunction onmessage はその名前でグローバルプロパティを定義しますが、Worker を生成したウェブページが送信したメッセージを受け取る関数を登録しません)。これは再帰的に開始して、計算の反復処理を行うために自身のコピーを生成します。

+

ワーカーは onmessage プロパティを、ワーカーのオブジェクトの postMessage() が呼び出されたときにメッセージを受け取る関数に設定します (これはその名前の変数関数を定義することとは違いますので注意してください。 var onmessagefunction onmessage は、これらの名前のグローバルグローバルプロパティを定義しますが、ワーカーを作成したウェブページから送信されたメッセージを受信するように関数を登録するわけではありません)。これは最適に開始して、それぞれの計算の反復処理を扱うために自分自身のコピーを起動します。

-

HTML コード

+

HTML コード

-
<!DOCTYPE html>
+
<!DOCTYPE html>
 <html>
   <head>
     <meta charset="UTF-8"  />
@@ -677,48 +678,72 @@ onmessage = function(event) {
 </html>
 
-

ウェブページは ID result を持つ div 要素を作成して、結果を表示するために使用します。そして、Worker を生成します。Worker を生成した後は、onmessage ハンドラを div 要素の内容物を指定することで結果を表示するように、また onerror ハンドラはエラーメッセージをダンプするように設定します。

+

ウェブページは result という ID を持つ div 要素を作成して、結果を表示するために使用します。そして、ワーカーを起動します。ワーカーを起動した後は、onmessage ハンドラーを div 要素の内容を指定することで結果を表示するように構成し、また onerror ハンドラーはエラーメッセージをダンプするように設定します。

-

最後に、 Worker を開始するためにメッセージを送信します。

+

最後に、ワーカーを開始するためにメッセージを送信します。

この例のデモを試してください

-

バックグラウンドでのウェブ入出力の実行

+

バックグラウンドでのウェブ入出力の実行

-

このサンプルは、 Using workers in extensions の記事に掲載しています。

+

この例は、 Using workers in extensions の記事に掲載しています。

-

複数の Worker にタスクを分割する

+

複数のワーカーにタスクを分割する

-

マルチコアのコンピュータが次第に一般化することで複数の Worker に複雑な計算処理を分割することが有用になり、それらのタスクを複数の CPU コアで実行することが可能になります。

+

マルチコアのコンピューターが一般的になってきたことで複数のワーカーに複雑な計算処理を分割することが有用になり、それらのタスクを複数の CPU コアで実行することが可能になります。

-

その他の Worker

+

その他のワーカー

-

Dedicated Worker や Shared Worker に加えて、他の種類の Worker を使用できます:

+

専用ワーカーや共有ワーカーに加えて、利用できる他の種類のワーカーがあります。

    -
  • Service Worker は本質的に、ウェブアプリケーション、ブラウザー、ネットワークの間 (可能であれば) でプロキシサーバーとして振る舞います。これは、例えば効果的なオフライン体験、ネットワークリクエストへの介入、ネットワークが利用可能かやサーバー上で更新された資源に応じて適切なアクションを行うなどを意図しています。また、プッシュ通知やバックグラウンド同期 API へのアクセスも可能です。
  • -
  • Chrome Worker は、アドオンを開発していて拡張機能で Worker の使用を望んでおり、また Worker で js-ctypes にアクセスする場合に使用できる、 Firefox 限定の Worker です。詳しくは {{domxref("ChromeWorker")}} をご覧ください。
  • -
  • Audio Worker は、Web Worker のコンテキスト内でスクリプトによるオーディオ処理を直接実行する機能を提供します。
  • +
  • ServiceWorker は、基本的に、ウェブアプリケーションと、ブラウザーおよびネットワーク (利用可能な場合) との間に位置するプロキシーサーバーとして機能します。これは、効果的なオフライン操作の構築ができるようにすること目的としています。ネットワークリクエストを傍受し、ネットワークが利用可能かどうかや、サーバー上の更新された資産に基づいて、適切なアクションをとります。また、プッシュ通知やバックグラウンド同期の API にもアクセスできるようになります。
  • +
  • Chrome Worker は Firefox 独自の種類のワーカーであり、アドオンを開発していて、拡張機能でワーカーを使用したい場合、ワーカーから js-ctypes にアクセスしたい場合に使用することができます。詳しくは {{domxref("ChromeWorker")}} をご覧ください。
  • +
  • Audio Worklet は、ワークレット (ワーカーの軽量版) のコンテキスト内でスクリプトによるオーディオ処理を直接実行する機能を提供します。
-

Worker で使用できる関数とインターフェイス

+

ワーカースレッドのデバッグ

+ +

ほとんどのブラウザーは、 JavaScript デバッガーでワーカースレッドのデバッグを、メインスレッドのデバッグとまったく同じ方法で対応しています。たとえば、 Firefox と Chrome の両方で、メインスレッドとアクティブなワーカースレッドの両方の JavaScript ソースファイルを一覧表示し、これらのファイルをすべて開いてブレークポイントやログポイントを設定することができます。

+ +

下の画面ショットは、 Firefox での例です。ソースリストには、別のワーカースレッドで実行されている worker.js が表示されています。このファイルを選択すると、メイン スレッドで実行されているコードと同様に、ソースペインで開かれます。

+ +

+ +
+

: ワーカーのスクリプトは必要になったときに読み込まれるため、ページが読み込まれたての時にはソースリストに現れていないかもしれません。

+
+ +

ソースパネルの中では通常の方法でワーカースレッドにブレークポイントまたはログポイント) を設定することができます。実行が一時停止されると、デバッガーのコンテキストが更新され、正しいブレークポイントインラインの変数のプレビューコールスタックなどが期待通りに表示されます。

+ +

+ +
+

: 詳しくは Firefox JavaScript Debugger を参照してください。

+
-

以下を含む、ほとんどの標準的な JavaScript 機能を Web Worker 内で使用できます:

+

ワーカーで使用できる関数とインターフェイス

+ +

標準的な JavaScript 機能のほとんどが Web Worker 内で使用できます。以下のものを含みます。

  • {{domxref("Navigator")}}
  • {{domxref("XMLHttpRequest")}}
  • {{jsxref("Global_Objects/Array", "Array")}}、{{jsxref("Global_Objects/Date", "Date")}}、{{jsxref("Global_Objects/Math", "Math")}}、{{jsxref("Global_Objects/String", "String")}}
  • -
  • {{domxref("WindowTimers.setTimeout")}} および {{domxref("WindowTimers.setInterval")}}
  • +
  • {{domxref("WindowOrWorkerGlobalScope.setTimeout")}} および {{domxref("WindowOrWorkerGlobalScope.setInterval")}}
-

Worker で実行できないことは主に、親ページに直接影響を与えるものです。これは、 DOM の操作やページのオブジェクトを使用することを含みます。{{domxref("DedicatedWorkerGlobalScope.postMessage")}} を使用してメインスクリプトにメッセージを戻してから変更操作を行う形で、間接的に実行しなければなりません。

+

ワーカーで実行できないことは主に、親ページに直接影響を与えるものです。これは、 DOM の操作やページのオブジェクトを使用することを含みます。{{domxref("DedicatedWorkerGlobalScope.postMessage")}} を使用してメインスクリプトにメッセージを戻してから変更操作を行う形で、間接的に実行しなければなりません。

+ +
+

あるメソッドがワーカーで利用できるかどうかは、サイト https://worker-playground.glitch.me/ を使ってテストできます。例えば、Firefox 84 でサイトに EventSource と入力すると、サービスワーカーではサポートされていないが、専用ワーカーや共有ワーカーではサポートされていることがわかります。

+
-

メモ: Worker で使用できる関数の完全なリストは、Worker で使用できる関数とインターフェイスでご覧ください。

+

メモ: ワーカーで使用できる関数の完全なリストは、ワーカーで使用できる関数とインターフェイスでご覧ください。

-

仕様書

+

仕様書

@@ -735,10 +760,10 @@ onmessage = function(event) {
-

関連情報

+

関連情報

-- cgit v1.2.3-54-g00ecf