From 33058f2b292b3a581333bdfb21b8f671898c5060 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:40:17 -0500 Subject: initial commit --- .../index.html | 380 +++++++++++ files/ja/web/api/web_workers_api/index.html | 99 +++ .../structured_clone_algorithm/index.html | 112 ++++ .../web_workers_api/using_web_workers/index.html | 744 +++++++++++++++++++++ 4 files changed, 1335 insertions(+) create mode 100644 files/ja/web/api/web_workers_api/functions_and_classes_available_to_workers/index.html create mode 100644 files/ja/web/api/web_workers_api/index.html create mode 100644 files/ja/web/api/web_workers_api/structured_clone_algorithm/index.html create mode 100644 files/ja/web/api/web_workers_api/using_web_workers/index.html (limited to 'files/ja/web/api/web_workers_api') diff --git a/files/ja/web/api/web_workers_api/functions_and_classes_available_to_workers/index.html b/files/ja/web/api/web_workers_api/functions_and_classes_available_to_workers/index.html new file mode 100644 index 0000000000..73e94ffb7a --- /dev/null +++ b/files/ja/web/api/web_workers_api/functions_and_classes_available_to_workers/index.html @@ -0,0 +1,380 @@ +--- +title: Web Workers が使用できる関数とクラス +slug: Web/API/Web_Workers_API/Functions_and_classes_available_to_workers +tags: + - Reference + - Web + - Web Worker + - Worker +translation_of: Web/API/Web_Workers_API/Functions_and_classes_available_to_workers +--- +

標準的な JavaScript の関数({{jsxref("String")}} や {{jsxref("Array")}}、{{jsxref("Object")}}、 {{jsxref("JSON")}} など)に加えて、DOMから worker に利用できる様々な関数があります。この記事ではそれらの機能のリストを提供します。

+ +

Worker は、現在の window とは異なるグローバルコンテキスト、 {{domxref("DedicatedWorkerGlobalScope")}} で実行されます。既定では {{domxref("Window")}} のメソッドとプロパティは使用できませんが、Window に似ている {{domxref("DedicatedWorkerGlobalScope")}} は {{domxref("WindowTimers")}} と {{domxref("WindowBase64")}} を実装しています。

+ +

worker の種類別のプロパティとメソッドの比較

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
関数専用 workers共有 workersサービス workersChrome workers {{Non-standard_inline}}workers の外側
{{domxref("WindowBase64.atob", "atob()")}}{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("Window")}} で使用可能。
{{domxref("WindowBase64.btoa", "btoa()")}}{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("Window")}} で使用可能。
{{domxref("WindowTimers.clearInterval", "clearInterval()")}}{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("Window")}} で使用可能。
{{domxref("WindowTimers.clearTimeout", "clearTimeout()")}}{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("Window")}} で使用可能。
{{domxref("Window.dump()", "dump()")}} {{non-standard_inline}}{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("Window")}} で使用可能。
{{domxref("WindowTimers.setInterval", "setInterval()")}}{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("Window")}} で使用可能。
{{domxref("WindowTimers.setTimeout", "setTimeout()")}}{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("Window")}} で使用可能。
{{domxref("WorkerGlobalScope.importScripts", "importScripts()")}}{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。使用不可。
{{domxref("WorkerGlobalScope.close", "close()")}} {{non-standard_inline}}{{domxref("WorkerGlobalScope")}} で使用可能。{{domxref("WorkerGlobalScope")}} で使用可能。使用可能だが、何も実行しない。不明。使用不可。
{{domxref("DedicatedWorkerGlobalScope.postMessage", "postMessage()")}}{{domxref("DedicatedWorkerGlobalScope")}} で使用可能。使用不可。使用不可。不明。使用不可。
+ +

worker で使用できる API

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
関数機能Gecko(Firefox)のサポート状況IE のサポート状況Blink(Chrome と Opera) のサポート状況WebKit(Safari) のサポート状況
{{domxref("Broadcast_Channel_API","Broadcast Channel API")}}同じ {{glossary("origin", "オリジン")}}(通常は同じサイトのページ)で {{glossary("browsing context", "ブラウジングコンテキスト")}}(window 、 tabframe、あるいはiframe)間の単純な通信ができる。{{ CompatGeckoDesktop(38)}}{{CompatNo}}{{CompatNo}}{{CompatNo}}
{{domxref("Cache", "Cache")}}Cache API は現在のオリジンと関連付けられたキャッシュストレージをプログラムで制御する機能を提供する。{{CompatVersionUnknown}}{{CompatNo}}{{ CompatChrome(43) }}{{CompatUnknown}}
{{domxref("Channel_Messaging_API", "Channel Messaging API")}} +

同じ document に添付されている異なるブラウジングコンテキスト(たとえば、2つのiFrame、あるいはメインの document とiFrame、{{domxref("SharedWorker")}} を介した2つの document 、あるいは2つの worker )にて、2つの別々のスクリプトが2 つのポートを介して 直接通信できる。

+
{{ CompatGeckoDesktop(41)}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}
{{domxref("Console", "Console API")}}ブラウザーのデバッグコンソールへのアクセスを提供する(たとえば、Firefox の Web コンソール)。どのように動作するかの詳細はブラウザーごとに異なるが、一般的に提供されている機能セットのデファクトである。{{ CompatGeckoDesktop(38)}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}
{{domxref("CustomEvent")}}CustomEvent インターフェースは、あらゆる用途でアプリケーションによって初期化されるイベントを表す。{{ CompatGeckoDesktop(48)}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}
{{domxref("Data_Store_API", "Data Store")}}複数の Firefox OS アプリケーションで、素早く効率的かつセキュアな相互のデータの保存や共有を行うための強力で柔軟なストレージ機構。v1.0.1 から、Firefox OS 内部(認定の通った)アプリケーションのみ。{{CompatNo}}{{CompatNo}}{{CompatNo}}
{{domxref("DOMRequest")}} と {{domxref("DOMCursor")}}それぞれ、これらのオブジェクトは進行中の操作と(たとえば、成功時や失敗時の操作に反応するリスナを使って)、結果リストを跨いだ進行中の操作を表す。{{ CompatGeckoDesktop(41)}}{{CompatUnknown}}{{CompatUnknown}}{{CompatUnknown}}
{{domxref("Fetch_API", "Fetch")}}Fetch 仕様はリソースを取得について、最新定義と、取得用の API (たとえば、ネットワーク経由で)を提供する。多くは{{ CompatGeckoDesktop(34)}} に(設定が必要)、いくつかの機能はそれ以降で。{{CompatNo}}{{ CompatChrome(42) }}
+ {{ CompatChrome(41) }} 設定が必要
{{CompatNo}}
{{domxref("FileReader")}}この API では、 {{domxref("Blob")}} と {{domxref("File")}} オブジェクトの非同期読み取りが可能。{{CompatGeckoDesktop(46)}}{{CompatNo}}{{CompatVersionUnknown}}{{CompatNo}}
{{domxref("FileReaderSync")}}この API では、{{domxref("Blob")}} と {{domxref("File")}} オブジェクトの同期読み取りが可能。worker 内でのみ実行可能な API。{{CompatGeckoDesktop(8)}}{{CompatNo}}{{CompatNo}}{{CompatNo}}
{{domxref("FormData")}}FormData オブジェクトは、XMLHttpRequest send() メソッドを使用して送信できる Form フィールドとその値を表す key/value ペアのセットを簡単に構築する方法を提供する。{{CompatUnknown}} ({{CompatGeckoDesktop(39)}} で実装されているはずである){{CompatUnknown}}{{CompatVersionUnknown}}{{CompatUnknown}}
{{domxref("ImageData")}}{{domxref("canvas")}} 要素の領域の下にあるピクセルデータ。このデータ操作は、Web Worker に委任したほうが適しているような、複雑な処理になりうる。{{CompatGeckoDesktop(25)}}{{CompatNo}}{{CompatNo}}{{CompatNo}}
{{domxref("IndexedDB_API", "IndexedDB")}}シンプルな値と階層的なオブジェクトを保持するレコードを保存するデータベース。{{CompatGeckoDesktop(37)}}, {{domxref("IDBCursorWithValue")}} は {{CompatGeckoDesktop(42)}} から。10.0{{CompatVersionUnknown}}{{CompatNo}}
Network Information APIシステムの接続についての情報を汎用的な接続タイプ(例えば 'wifi', 'cellular' など)の用語で提供する。{{CompatGeckoMobile(53)}} モバイルのみ{{CompatVersionUnknown}} モバイルのみ{{CompatNo}}{{CompatNo}}
{{domxref("Notifications_API", "Notifications")}}Web ページがエンドユーザーへのシステム通知の表示を制御できるようにする。{{CompatGeckoDesktop(41)}}{{CompatUnknown}}{{CompatUnknown}}{{CompatUnknown}}
{{domxref("Performance")}}Performance インターフェースは、指定されたページのタイミング関連のパフォーマンス情報を表す。{{ CompatGeckoDesktop("34.0") }}{{CompatUnknown}}{{ CompatChrome("33.0") }}{{CompatUnknown}}
{{domxref("PerformanceEntry")}}, {{domxref("PerformanceMeasure")}}, {{domxref("PerformanceMark")}}, {{domxref("PerformanceObserver")}}, {{domxref("PerformanceResourceTiming")}}アプリケーションのネットワークの性能についていくつかの面から詳細なデータを獲得、分析することを可能にする。{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}
{{jsxref("Promise")}}非同期関数を記述できる JavaScript オブジェクト。{{CompatGeckoDesktop(28)}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}
Server-sent eventsサーバーから、接続が開いた後に、あらゆる箇所のウェブページにデータをプッシュさせる。{{CompatGeckoDesktop(53)}} (今のところ専用 worker と共有 worker でのみ有効; service worker では無効){{CompatUnknown}}{{CompatVersionUnknown}}{{CompatUnknown}}
{{domxref("ServiceWorkerRegistration")}}標準 worker の内部から service worker を登録して、関連する機能を使用できる。{{CompatGeckoDesktop(40)}}{{CompatNo}}{{CompatVersionUnknown}}{{CompatNo}}
{{domxref("TextEncoder")}} と {{domxref("TextDecoder")}}特定のエンコーディングに エンコード、またはでコードできる新しい {{domxref("TextEncoder")}} や {{domxref("TextDecoder")}} を生成して返す。{{CompatGeckoDesktop(20)}}{{CompatNo}}{{CompatNo}}{{CompatNo}}
{{ domxref("URL") }} +

Worker にアクセスできる {{domxref("Blob")}} とともに URL.createObjectURLURL.revokeObjectURL 静的メソッドを使用できる。
+ Worker は {{domxref("URL.URL", "URL()")}} コンストラクタを使用して新しい URL を生成し、返されたオブジェクトの通常のメソッドを呼び出せる。

+
{{CompatGeckoDesktop(21)}}。URL() コンストラクタは {{CompatGeckoDesktop(26)}} から。{{CompatNo}}{{CompatNo}}{{CompatNo}}
{{domxref("OffscreenCanvas")}} の WebGLWebGL(Web グラフィックライブラリ)は、プラグインを使用せずにブラウザー互換性を保ちながらインタラクティブな 3D と 2D レンダリングができる JavaScript API である。{{CompatGeckoDesktop(44)}}(設定で有効化する)。about:config で、gfx.offscreencanvas.enabled を true に設定する。{{CompatNo}}{{CompatNo}}{{CompatNo}}
{{domxref("WebSocket")}}新しい {{domxref("WebSocket")}} オブジェクトを生成して返す。これは標準の WebSocket() コンストラクタの動作を模倣する。{{CompatGeckoDesktop(37)}}11.0{{CompatVersionUnknown}}{{CompatVersionUnknown}}
{{domxref("Worker")}}新しい {{ domxref("Worker") }} を生成する。worker はより多くの worker を生成できる。{{CompatGeckoDesktop("1.9.1")}}10.0{{CompatNo}} crbug.com/31666 を見てください。{{CompatNo}}
{{domxref("WorkerGlobalScope")}}グローバルスコープの worker。このオブジェクトは Worker 特有の関数を定義する。{{CompatVersionUnknown}}10.0{{CompatVersionUnknown}}{{CompatVersionUnknown}}
{{domxref("WorkerLocation")}}worker で使用可能な {{domxref("Location")}} インターフェースのサブセット。{{CompatGeckoDesktop(1.9.2)}}10.0{{CompatVersionUnknown}}{{CompatVersionUnknown}}
{{domxref("WorkerNavigator")}}worker で使用可能な {{domxref("Navigator")}} インターフェースのサブセット。 +

基本実装 {{CompatVersionUnknown}}
+ {{domxref("NavigatorID.appCodeName", "appCodeName")}}、{{domxref("NavigatorID.product", "product")}}、{{domxref("NavigatorID.taintEnabled", "taintEnabled()")}}:{{CompatGeckoDesktop(28)}}
+ {{domxref("WorkerNavigator.onLine", "onLine")}}:{{CompatGeckoDesktop(29)}}
+ {{domxref("NavigatorLanguage")}}: {{CompatVersionUnknown}}

+
{{domxref("NavigatorID.appName", "appName")}}、{{domxref("NavigatorID.appVersion", "appVersion")}}、{{domxref("WorkerNavigator.onLine", "onLine")}}、{{domxref("NavigatorID.platform", "platform")}}、{{domxref("NavigatorID.userAgent", "userAgent")}}: 10.0
+ Other: {{CompatNo}}
{{CompatVersionUnknown}}{{CompatVersionUnknown}}
{{domxref("XMLHttpRequest")}}新しい {{domxref("XMLHttpRequest")}} オブジェクトを生成して返す。これは標準の XMLHttpRequest() コンストラクタの動作を模倣する。XMLHttpRequestresponseXMLchannel 属性は常に null を返すことに注意。 +

基本: {{CompatGeckoDesktop("1.9.1")}}

+ +

{{domxref("XMLHttpRequest.response", "response")}} と {{domxref("XMLHttpRequest.responseType", "responseType")}} は、{{CompatGeckoDesktop("10")}} から使用可能。

+ +

{{domxref("XMLHttpRequest.timeout", "timeout")}} と {{domxref("XMLHttpRequest.ontimeout", "ontimeout")}} は、{{CompatGeckoDesktop("13")}} から使用可能。

+
{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}
+ +

関連項目

+ + diff --git a/files/ja/web/api/web_workers_api/index.html b/files/ja/web/api/web_workers_api/index.html new file mode 100644 index 0000000000..e4d9678f40 --- /dev/null +++ b/files/ja/web/api/web_workers_api/index.html @@ -0,0 +1,99 @@ +--- +title: Web Workers API +slug: Web/API/Web_Workers_API +tags: + - API + - DOM + - Web Workers + - Workers +translation_of: Web/API/Web_Workers_API +--- +
{{DefaultAPISidebar("Web Workers API")}}
+ +

Web Worker とは、ウェブアプリケーションにおけるスクリプトの処理をメインとは別のスレッドに移し、バックグラウンドでの実行を可能にする仕組みのことです。時間のかかる処理を別のスレッドに移すことが出来るため、 UI を担当するメインスレッドの処理を中断・遅延させずに実行できるという利点があります。

+ +

Web Worker の概念と使い方

+ +

{{DOMxRef("Worker")}} オブジェクトは {{DOMxRef("Worker.Worker", "Worker()")}} などのコンストラクターで生成されるオブジェクトで、名前を持つ JavaScript ファイルを実行します。 Worker のスレッドで実行されるコードはこのファイルに書かれており、今いる {{DOMxRef("window")}} とは別のグローバルなコンテキストの中で Worker がコードを実行します。Dedicated Worker (専用ワーカー) の場合、そのコンテキストは {{DOMxRef("DedicatedWorkerGlobalScope")}} オブジェクトで表現されます (通常の Worker は単一のスクリプトで使用されますが、 Worker を共有する際は {{DOMxRef("SharedWorkerGlobalScope")}} を使用します)。

+ +

Worker のスレッドではあらゆるコードを実行できますが、いくつか例外があります。例えば、 Worker から DOM を直接操作することは出来ません。また、 {{DOMxRef("window")}} にデフォルトで用意されているメソッドやプロパティには Worker から使用できないものもあります。しかし、 WebSocketsIndexedDB のようなデータストレージに加え、 Firefox OS における Data Store API など、 window に含まれていても使用できるものは数多くあります。詳しくは Worker から使用できる関数とクラス を参照してください。

+ +

Worker とメインスレッドとの間では、メッセージのシステムを通してデータがやり取りされます。両者は postMessage() メソッドを使ってメッセージを送信し、受け取ったメッセージには onmessage イベントハンドラーで返信します (メッセージは {{Event("Message")}} イベントの data 属性に格納されます)。なお、送信したデータは受取先でコピーされます (共有ではありません)。

+ +

メインスレッドのページと同じオリジンであれば、 Web Workers は新しい Worker をいくつでも生成できます。また、 Worker はネットワーク I/O において XMLHttpRequest を使用しますが、 XMLHttpRequest における responseXMLchannel 属性は必ず null を返す点で通常と異なります。

+ +

Dedicated Worker の他にも、 Worker の種類には以下のようなものがあります。

+ + + +
+

メモ: Web Worker の仕様にあるように、Worker のエラーイベントはバブルするべきではありません (see {{bug(1188141)}}。これは Firefox 42 で実装されました。

+ +

 

+
+ +

Web Worker インターフェイス

+ +
+
{{DOMxRef("AbstractWorker")}}
+
{{DOMxRef("Worker")}} や {{DOMxRef("SharedWorker")}} など、すべての Worker に共通な抽象オブジェクトです。
+
{{DOMxRef("Worker")}}
+
実行している Worker のスレッドを表します。実行している Worker のコードへメッセージを送る際に用います。
+
{{DOMxRef("WorkerLocation")}}
+
{{DOMxRef("Worker")}} で実行されるスクリプトの絶対位置を定義します。
+
{{DOMxRef("SharedWorker")}}
+
複数のウィンドウ、 iframe、ワーカーなどいくつかの{{glossary("browsing context", "閲覧コンテキスト")}}から「アクセス可能な」具体的な種類の Worker を表します。
+
{{DOMxRef("WorkerGlobalScope")}}
+
{{DOMxRef("Window")}} のように通常のウェブコンテンツと同じ動作をする Worker の一般的なスコープを表します。これと異なる種類の Worker は、このインタフェースに独自の機能をいくつか加えたスコープを持ちます。
+
{{DOMxRef("DedicatedWorkerGlobalScope")}}
+
Dedicated Worker のスコープを表します。 {{DOMxRef("WorkerGlobalScope")}} を継承しており、独自の機能がいくつか加えられています。
+
{{DOMxRef("SharedWorkerGlobalScope")}}
+
Shared Worker のスコープを表します。 {{DOMxRef("WorkerGlobalScope")}} を継承しており、独自の機能がいくつか加えられています。
+
{{DOMxRef("WorkerNavigator")}}
+
ユーザエージェント (クライアント) に関する識別名と状態を表します。
+
+ +

+ +

簡単なデモと基本的な使い方は以下を参照してください。

+ + + +

このデモの動く仕組みを詳しく知りたい場合は Web Worker を使用するを参照してください。

+ +

仕様

+ + + + + + + + + + + + + + +
仕様書状態備考
{{SpecName("HTML WHATWG", "workers.html#workers", "Web Workers")}}{{Spec2("HTML WHATWG")}}初回定義
+ +

あわせて参照

+ + diff --git a/files/ja/web/api/web_workers_api/structured_clone_algorithm/index.html b/files/ja/web/api/web_workers_api/structured_clone_algorithm/index.html new file mode 100644 index 0000000000..0be43a0cf7 --- /dev/null +++ b/files/ja/web/api/web_workers_api/structured_clone_algorithm/index.html @@ -0,0 +1,112 @@ +--- +title: 構造化複製アルゴリズム +slug: Web/API/Web_Workers_API/Structured_clone_algorithm +translation_of: Web/API/Web_Workers_API/Structured_clone_algorithm +--- +

構造化複製アルゴリズム は複雑な JavaScript オブジェクトをコピーするためのアルゴリズムです。これは {{domxref("Worker.postMessage()", "postMessage()")}} を介して Worker と送受信するとき、IndexedDB にオブジェクトを格納するとき、他の API のためにオブジェクトをコピーするときなど、データ転送時に内部で用いられています。無限ループを避けるため、以前にアクセスした参照のマップを保持しながら、入力オブジェクトを再帰処理することで複製していきます。

+ +

構造化複製で動作しないもの

+ + + +
+

メモ: ネイティブの Error 型は Chrome では複製できます。Firefox は 対応中 です。

+
+ +

サポート済みの型

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
オブジェクトの型備考
すべてのプリミティブ型symbol を除く
Boolean オブジェクト
String オブジェクト
Date
RegExplastIndex フィールドは保持されません。
{{ domxref("Blob") }}
{{ domxref("File") }}
{{ domxref("FileList") }}
ArrayBuffer
ArrayBufferView他の 型付き配列 を含む
{{ domxref("ImageBitmap") }}
{{ domxref("ImageData") }}
Array
Objectこれはプレーンオブジェクト (オブジェクトリテラルなど) のみ を含みます
Map
Set
+ +

関連情報

+ + 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 new file mode 100644 index 0000000000..e7719ecabe --- /dev/null +++ b/files/ja/web/api/web_workers_api/using_web_workers/index.html @@ -0,0 +1,744 @@ +--- +title: Web Worker の使用 +slug: Web/API/Web_Workers_API/Using_web_workers +tags: + - Advanced + - Firefox + - Guide + - HTML5 + - JavaScript + - 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 Workers API

+ +

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

+ +

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

+ +
+

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

+
+ +

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

+ +

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

+ +

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

+ +

Dedicated Worker

+ +

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

+ +

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

+ +

Worker 機能を検出する

+ +

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

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

Dedicated Worker を生成する

+ +

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

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

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

+ +

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

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

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

+ +

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

+ +
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 を使用して、Worker から返されたメッセージに応答します:

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

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

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

Worker の終了

+ +

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

+ +
myWorker.terminate();
+ +

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

+ +

エラーハンドリング

+ +

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

+ +

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

+ +

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

+ +
+
message
+
人間が読み取れるエラーメッセージです。
+
filename
+
エラーが発生したスクリプトのファイル名です。
+
lineno
+
スクリプトファイル内でエラーが発生した場所の行番号です。
+
+ +

サブ Worker の生成

+ +

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

+ +

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

+ +

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

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

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

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

Shared Worker

+ +

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

+ +

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

+ +
+

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

+
+ +
+

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

+
+ +

Shared Worker の生成

+ +

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

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

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

+ +

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

+ +
+

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

+
+ +

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

+ +

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

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

Worker に移ります。こちらは若干複雑さが増しています (worker.js):

+ +
onconnect = function(e) {
+  var port = e.ports[0];
+
+  port.onmessage = function(e) {
+    var workerResult = 'Result: ' + (e.data[0] * e.data[1]);
+    port.postMessage(workerResult);
+  }
+}
+ +

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

+ +

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

+ +

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

+ +

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

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

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

+ +

スレッドセーフについて

+ +

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

+ +

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

+ +

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

+ +

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

+ +
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 を継承します。

+ +

Worker とのデータ伝送の詳細

+ +

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

+ +

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

+ +
function emulateMessage(vVal) {
+    return eval('(' + JSON.stringify(vVal) + ')');
+}
+
+// テスト
+
+// テスト #1
+var example1 = new Number(3);
+console.log(typeof example1); // object
+console.log(typeof emulateMessage(example1)); // number
+
+// テスト #2
+var example2 = true;
+console.log(typeof example2); // boolean
+console.log(typeof emulateMessage(example2)); // boolean
+
+// テスト #3
+var example3 = new String('Hello World');
+console.log(typeof example3); // object
+console.log(typeof emulateMessage(example3)); // string
+
+// テスト #4
+var example4 = {
+    'name': 'John Smith',
+    "age": 43
+};
+console.log(typeof example4); // object
+console.log(typeof emulateMessage(example4)); // object
+
+// テスト #5
+function Animal(sType, nAge) {
+    this.type = sType;
+    this.age = nAge;
+}
+var example5 = new Animal('Cat', 3);
+alert(example5.constructor); // Animal
+alert(emulateMessage(example5).constructor); // Object
+ +

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

+ +

example.html (メインページ)

+ +
var myWorker = new Worker('my_task.js');
+
+myWorker.onmessage = function(oEvent) {
+  console.log('Worker said : ' + oEvent.data);
+};
+
+myWorker.postMessage('ali');
+ +

my_task.js (Worker)

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

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

+ +

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

+ +

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

+ +

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

+ +

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

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

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

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

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

+ +
/*
+  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)
+    });
+}
+ +

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

+ +
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);
+    } else {
+        this.defaultListener.call(instance, event.data);
+    }
+}
+
+ +

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

+ +
var queryableFunctions = {
+    getDifference: function(a, b) {
+        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)
+    });
+}
+
+/* This method is called when main page calls QueryWorker's postMessage method directly*/
+function defaultReply(message) {
+    // 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);
+    }
+}
+
+ +

ここでは、完全な実装を紹介します。

+ +

example.html (メインページ)

+ +
<!doctype html>
+  <html>
+    <head>
+      <meta charset="UTF-8"  />
+      <title>MDN Example - Queryable worker</title>
+    <script type="text/javascript">
+    /*
+      QueryableWorker instances methods:
+        * sendQuery(queryable function name, argument to pass 1, argument to pass 2, etc. etc): calls a Worker's queryable function
+        * postMessage(string or JSON Data): see Worker.prototype.postMessage()
+        * terminate(): terminates the Worker
+        * addListener(name, function): adds a listener
+        * removeListener(name): removes a listener
+      QueryableWorker instances properties:
+        * 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 = {};
+
+      this.defaultListener = defaultListener || function() {};
+
+      if (onError) {worker.onerror = onError;}
+
+      this.postMessage = function(message) {
+        worker.postMessage(message);
+      }
+
+      this.terminate = function() {
+        worker.terminate();
+      }
+
+      this.addListener = function(name, listener) {
+        listeners[name] = listener;
+      }
+
+      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.
+      */
+      this.sendQuery = function() {
+        if (arguments.length < 1) {
+          throw new TypeError('QueryableWorker.sendQuery takes at least one argument');
+          return;
+        }
+        worker.postMessage({
+          'queryMethod': arguments[0],
+          'queryMethodArguments': Array.prototype.slice.call(arguments, 1)
+        });
+      }
+
+      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);
+        } else {
+          this.defaultListener.call(instance, event.data);
+        }
+      }
+    }
+
+    // 独自の「照会可能な」 worker
+    var myTask = new QueryableWorker('my_task.js');
+
+    // 独自の「リスナー」
+    myTask.addListener('printStuff', function (result) {
+      document.getElementById('firstLink').parentNode.appendChild(document.createTextNode('The difference is ' + result + '!'));
+    });
+
+    myTask.addListener('doAlert', function (time, unit) {
+      alert('Worker waited for ' + time + ' ' + unit + ' :-)');
+    });
+</script>
+</head>
+<body>
+  <ul>
+    <li><a id="firstLink" href="javascript:myTask.sendQuery('getDifference', 5, 3);">What is the difference between 5 and 3?</a></li>
+    <li><a href="javascript:myTask.sendQuery('waitSomeTime');">Wait 3 seconds</a></li>
+    <li><a href="javascript:myTask.terminate();">terminate() the Worker</a></li>
+  </ul>
+</body>
+</html>
+ +

my_task.js (Worker)

+ +
var queryableFunctions = {
+  // 例 #1: 2 つの値の差を得る:
+  getDifference: function(nMinuend, nSubtrahend) {
+      reply('printStuff', nMinuend - nSubtrahend);
+  },
+  // 例 #2: 3 秒待つ
+  waitSomeTime: function() {
+      setTimeout(function() { reply('doAlert', 3, 'seconds'); }, 3000);
+  }
+};
+
+// システム関数
+
+function defaultReply(message) {
+  // メインページが queryableWorker.postMessage() メソッドを直接呼び出したときに限り実行される、デフォルトの PUBLIC 関数
+  // 何らかの処理
+}
+
+function reply() {
+  if (arguments.length < 1) { throw new TypeError('reply - not enough arguments'); return; }
+  postMessage({ 'queryMethodListener': arguments[0], 'queryMethodArguments': Array.prototype.slice.call(arguments, 1) });
+}
+
+onmessage = function(oEvent) {
+  if (oEvent.data instanceof Object && oEvent.data.hasOwnProperty('queryMethod') && oEvent.data.hasOwnProperty('queryMethodArguments')) {
+    queryableFunctions[oEvent.data.queryMethod].apply(self, oEvent.data.queryMethodArguments);
+  } else {
+    defaultReply(oEvent.data);
+  }
+};
+ +

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

+ +

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

+ +

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

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

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

+
+ +

埋め込み Worker

+ +

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

+ +
<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8" />
+<title>MDN Example - Embedded worker</title>
+<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 回だけレンダリング/リフローします。
+    var oFragm = document.createDocumentFragment();
+    oFragm.appendChild(document.createTextNode(sMsg));
+    oFragm.appendChild(document.createElement('br'));
+    document.querySelector('#logDisplay').appendChild(oFragm);
+  }
+</script>
+<script type="text/js-worker">
+  // MIME タイプが text/js-worker であるため、このスクリプトは JS エンジンに解釈されません。
+  onmessage = function(oEvent) {
+    postMessage(myVar);
+  };
+  // worker の残りのコードをここに置きます。
+</script>
+<script type="text/javascript">
+  // MIME タイプが text/javascript であるため、このスクリプトは JS エンジンに解釈されます。
+
+  //
+  // 以前は 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 プロパティを生成します。
+  document.worker = new Worker(window.URL.createObjectURL(blob));
+
+  document.worker.onmessage = function(oEvent) {
+    pageLog('Received: ' + oEvent.data);
+  };
+
+  // Worker を開始します。
+  window.onload = function() { document.worker.postMessage(''); };
+</script>
+</head>
+<body><div id="logDisplay"></div></body>
+</html>
+ +

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

+ +

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

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

追加サンプル

+ +

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

+ +

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

+ +

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

+ +

JavaScript コード

+ +

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

+ +
var results = [];
+
+function resultReceiver(event) {
+  results.push(parseInt(event.data));
+  if (results.length == 2) {
+    postMessage(results[0] + results[1]);
+  }
+}
+
+function errorReceiver(event) {
+  throw event.data;
+}
+
+onmessage = function(event) {
+  var n = parseInt(event.data);
+
+  if (n == 0 || n == 1) {
+    postMessage(n);
+    return;
+  }
+
+  for (var i = 1; i <= 2; i++) {
+    var worker = new Worker('fibonacci.js');
+    worker.onmessage = resultReceiver;
+    worker.onerror = errorReceiver;
+    worker.postMessage(n - i);
+  }
+ };
+ +

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

+ +

HTML コード

+ +
<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8"  />
+    <title>Test threads fibonacci</title>
+  </head>
+  <body>
+
+  <div id="result"></div>
+
+  <script language="javascript">
+
+    var worker = new Worker('fibonacci.js');
+
+    worker.onmessage = function(event) {
+      document.getElementById('result').textContent = event.data;
+      dump('Got: ' + event.data + '\n');
+    };
+
+    worker.onerror = function(error) {
+      dump('Worker error: ' + error.message + '\n');
+      throw error;
+    };
+
+    worker.postMessage('5');
+
+  </script>
+  </body>
+</html>
+
+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

その他の Worker

+ +

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

+ + + +

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

+ +

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

+ + + +

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

+ +
+

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

+
+ +

仕様書

+ + + + + + + + + + + + + + +
仕様書状態備考
{{SpecName('HTML WHATWG', '#workers', 'Web workers')}}{{Spec2('HTML WHATWG')}}
+ +

関連情報

+ + -- cgit v1.2.3-54-g00ecf