diff options
author | Masahiro FUJIMOTO <mfujimot@gmail.com> | 2021-09-07 22:56:20 +0900 |
---|---|---|
committer | Masahiro FUJIMOTO <mfujimot@gmail.com> | 2021-09-07 22:56:20 +0900 |
commit | db091658bee048cac6a43ab7fe346ea7d420818a (patch) | |
tree | f551c4caac755cf43c99a5dccab68da21bf16765 /files/ja | |
parent | fe6f6abf2b7c497bf1f97f73a82dde7cf48eb79f (diff) | |
parent | 33a5bcbcd367750dc0b7376f692d5aacfb799303 (diff) | |
download | translated-content-db091658bee048cac6a43ab7fe346ea7d420818a.tar.gz translated-content-db091658bee048cac6a43ab7fe346ea7d420818a.tar.bz2 translated-content-db091658bee048cac6a43ab7fe346ea7d420818a.zip |
Merge branch 'main' into 20210818-Glossary/Type
Diffstat (limited to 'files/ja')
24 files changed, 1157 insertions, 1074 deletions
diff --git a/files/ja/mozilla/firefox/releases/69/index.html b/files/ja/mozilla/firefox/releases/69/index.html index 5f2a43d7e0..2fb85666a7 100644 --- a/files/ja/mozilla/firefox/releases/69/index.html +++ b/files/ja/mozilla/firefox/releases/69/index.html @@ -97,7 +97,7 @@ translation_of: Mozilla/Firefox/Releases/69 <ul> <li><a href="/ja/docs/Web/JavaScript/Reference/Classes#Field_declarations">パブリッククラスフィールド</a> をデフォルトで有効にしました ({{bug(1555464)}})。詳しくは <a href="/ja/docs/Web/JavaScript/Reference/Classes/Class_fields">Class fields</a> もご覧ください。</li> - <li>promise の拒絶イベントである <code><a href="/ja/docs/Web/API/Window/unhandledrejection_event">unhandledrejection</a></code> および <code><a href="/ja/docs/Web/API/Window/rejectionhandled_event">rejectionhandled</a></code> をデフォルトで有効にしました ({{bug(1362272)}})。これらの動作について詳しくは {{SectionOnPage("/docs/Web/JavaScript/Guide/Using_promises", "Promise rejection events")}} をご覧ください。</li> + <li>promise の拒否イベントである <code><a href="/ja/docs/Web/API/Window/unhandledrejection_event">unhandledrejection</a></code> および <code><a href="/ja/docs/Web/API/Window/rejectionhandled_event">rejectionhandled</a></code> をデフォルトで有効にしました ({{bug(1362272)}})。これらの動作について詳しくは {{SectionOnPage("/docs/Web/JavaScript/Guide/Using_promises", "Promise rejection events")}} をご覧ください。</li> </ul> <h3 id="HTTP" name="HTTP">HTTP</h3> diff --git a/files/ja/web/api/document/requeststorageaccess/index.html b/files/ja/web/api/document/requeststorageaccess/index.html index 7c1368fb23..b4952aa6bb 100644 --- a/files/ja/web/api/document/requeststorageaccess/index.html +++ b/files/ja/web/api/document/requeststorageaccess/index.html @@ -14,7 +14,7 @@ translation_of: Web/API/Document/requestStorageAccess --- <div>{{APIRef}}</div> -<p><strong><code>requestStorageAccess()</code></strong> は {{domxref("Document")}} インターフェイスのメソッドで、ファーストパーティのストレージへのアクセスが許可されたら解決し、アクセスが拒否されたら拒絶される {{jsxref("Promise")}} を返します。</p> +<p><strong><code>requestStorageAccess()</code></strong> は {{domxref("Document")}} インターフェイスのメソッドで、ファーストパーティのストレージへのアクセスが許可されたら解決し、アクセスが拒否されたら拒否される {{jsxref("Promise")}} を返します。</p> <h2 id="Conditions_for_granting_storage_access" name="Conditions_for_granting_storage_access">ストレージへのアクセスが許可される条件</h2> @@ -22,14 +22,14 @@ translation_of: Web/API/Document/requestStorageAccess <ol> <li>文書がすでにアクセスを許可されていれば、解決。</li> - <li>文書が null オリジンを持っていれば、拒絶。</li> + <li>文書が null オリジンを持っていれば、拒否。</li> <li>文書のフレームが主フレームであれば、解決。</li> <li>副フレームのオリジンが主フレームのものと同じであれば、解決。</li> <li>副フレームがサンドボックス化されていなければ、7へ飛ぶ。</li> - <li>副フレームにトークン <code>allow-storage-access-by-user-activation</code> がなければ、拒絶。</li> - <li>副フレームの親フレームが最上位フレームでなければ、拒絶。</li> - <li>ブラウザーがユーザージェスチャーを処理中でなければ、拒絶。</li> - <li>ブラウザーが持っている追加の規則をチェック。例えば、ホワイトリスト、ブラックリスト、端末上の分類、ユーザー設定、クリックジャック防止の推測、ユーザーへの明示的なパーミッションの確認など。いくつかの規則が満たされていなければ、拒絶。</li> + <li>副フレームにトークン <code>allow-storage-access-by-user-activation</code> がなければ、拒否。</li> + <li>副フレームの親フレームが最上位フレームでなければ、拒否。</li> + <li>ブラウザーがユーザージェスチャーを処理中でなければ、拒否。</li> + <li>ブラウザーが持っている追加の規則をチェック。例えば、ホワイトリスト、ブラックリスト、端末上の分類、ユーザー設定、クリックジャック防止の推測、ユーザーへの明示的なパーミッションの確認など。いくつかの規則が満たされていなければ、拒否。</li> <li>文書にクッキーやその他のサイトストレージへのアクセスを許可し、将来の {{domxref("Document.hasStorageAccess()")}} および <code>requestStorageAccess()</code> の呼び出しのためにその事実を保存。</li> </ol> @@ -99,7 +99,7 @@ translation_of: Web/API/Document/requestStorageAccess <h3 id="Return_value" name="Return_value">返値</h3> -<p>ファーストパーティのストレージへのアクセスが許可されたら <code>undefined</code> で満たされ、アクセスが拒否されたら拒絶される {{jsxref("Promise")}} です。</p> +<p>ファーストパーティのストレージへのアクセスが許可されたら <code>undefined</code> で満たされ、アクセスが拒否されたら拒否される {{jsxref("Promise")}} です。</p> <p>Promise が解決されると、 Promise が満たされたか拒否されたかに関わらず、ユーザージェスチャーが処理されているかのように解決ハンドラーが実行されます。</p> diff --git a/files/ja/web/api/mediadevices/getusermedia/index.html b/files/ja/web/api/mediadevices/getusermedia/index.html index 2ae1912292..53f62988fc 100644 --- a/files/ja/web/api/mediadevices/getusermedia/index.html +++ b/files/ja/web/api/mediadevices/getusermedia/index.html @@ -24,7 +24,7 @@ translation_of: Web/API/MediaDevices/getUserMedia <p>これは {{domxref("MediaStream")}} オブジェクトに解決する {{jsxref("Promise")}} を返します。ユーザーが拒否した場合や、一致するメディアが利用できない場合、 Promise はそれぞれ <code>NotAllowedError</code> または <code>NotFoundError</code> で拒否されます。</p> <div class="note"> -<p><strong>メモ:</strong> ユーザーが選択する必要が全くなく、リクエストを単純に無視できる場合、返却された Promise が解決または拒絶の<em>どちらにもならない</em>可能性があります。</p> +<p><strong>メモ:</strong> ユーザーが選択する必要が全くなく、リクエストを単純に無視できる場合、返却された Promise が解決または拒否の<em>どちらにもならない</em>可能性があります。</p> </div> <p>一般的に、 {{domxref("MediaDevices")}} のシングルトンオブジェクトは以下のように、 {{domxref("navigator.mediaDevices")}} を使用してアクセスします。</p> diff --git a/files/ja/web/api/navigator/getbattery/index.html b/files/ja/web/api/navigator/getbattery/index.html index a17409ec9a..b324dfb6eb 100644 --- a/files/ja/web/api/navigator/getbattery/index.html +++ b/files/ja/web/api/navigator/getbattery/index.html @@ -30,7 +30,7 @@ translation_of: Web/API/Navigator/getBattery <h2 id="Exceptions" name="Exceptions">例外</h2> -<p>このメソッドは真の例外を発生させません。代わりに、返された promise を拒絶し、 {{domxref("DOMException")}} の中に <code>name</code> を次のうちの一つに設定します。</p> +<p>このメソッドは真の例外を発生させません。代わりに、返されたプロミスが拒否され、 {{domxref("DOMException")}} の中に <code>name</code> を次のうちの一つに設定します。</p> <dl> <dt><code>SecurityError</code></dt> diff --git a/files/ja/web/api/promiserejectionevent/index.html b/files/ja/web/api/promiserejectionevent/index.html index 7f45e89bdf..1f7e1a8487 100644 --- a/files/ja/web/api/promiserejectionevent/index.html +++ b/files/ja/web/api/promiserejectionevent/index.html @@ -15,7 +15,7 @@ translation_of: Web/API/PromiseRejectionEvent --- <div>{{APIRef("HTML DOM")}}</div> -<p><span class="seoSummary"><strong><code>PromiseRejectionEvent</code></strong> インターフェイスは、 JavaScript の {{jsxref("Promise")}} が拒絶されたときにグローバルスクリプトコンテキストに送信されるイベントを表します。</span>これらのイベントは、測定やデバッグ目的に使用すると特に有益です。</p> +<p><span class="seoSummary"><strong><code>PromiseRejectionEvent</code></strong> インターフェイスは、 JavaScript の {{jsxref("Promise")}} が拒否されたときにグローバルスクリプトコンテキストに送信されるイベントを表します。</span>これらのイベントは、測定やデバッグ目的に使用すると特に有益です。</p> <h2 id="Constructor" name="Constructor">コンストラクター</h2> @@ -30,9 +30,9 @@ translation_of: Web/API/PromiseRejectionEvent <dl> <dt>{{domxref("PromiseRejectionEvent.promise")}} {{readonlyInline}}</dt> - <dd>拒絶された JavaScript の {{jsxref("Promise")}}。</dd> + <dd>拒否された JavaScript の {{jsxref("Promise")}}。</dd> <dt>{{domxref("PromiseRejectionEvent.reason")}} {{readOnlyInline}}</dt> - <dd>{{jsxref("Promise.reject()")}} に渡される Promise が拒絶された理由を示す値、または {{jsxref("Object")}}。</dd> + <dd>{{jsxref("Promise.reject()")}} に渡される Promise が拒否された理由を示す値、または {{jsxref("Object")}}。</dd> </dl> <h2 id="Methods" name="Methods">メソッド</h2> @@ -43,9 +43,9 @@ translation_of: Web/API/PromiseRejectionEvent <dl> <dt>{{Event("rejectionhandled")}}</dt> - <dd>JavaScript の {{jsxref("Promise")}} が拒絶され、promise の reject イベントハンドラーのコードが実行された後に発生する。</dd> + <dd>JavaScript の {{jsxref("Promise")}} が拒否され、promise の reject イベントハンドラーのコードが実行された後に発生する。</dd> <dt>{{Event("unhandledrejection")}}</dt> - <dd>reject に対するイベントハンドラーがない状態で JavaScript の {{jsxref("Promise")}} が拒絶されたときに発生する。</dd> + <dd>reject に対するイベントハンドラーがない状態で JavaScript の {{jsxref("Promise")}} が拒否されたときに発生する。</dd> </dl> <h2 id="Examples" name="Examples">例</h2> diff --git a/files/ja/web/api/promiserejectionevent/promise/index.html b/files/ja/web/api/promiserejectionevent/promise/index.html index ae55501f0d..64cf00fcd8 100644 --- a/files/ja/web/api/promiserejectionevent/promise/index.html +++ b/files/ja/web/api/promiserejectionevent/promise/index.html @@ -15,7 +15,7 @@ translation_of: Web/API/PromiseRejectionEvent/promise --- <div>{{APIRef("HTML DOM") }}</div> -<div>{{domxref("PromiseRejectionEvent")}}インターフェイスの読み取り専用プロパティである <code><strong>promise</strong></code> は、拒絶された JavaScript の {{jsxref("Promise")}} を表します。promise が拒絶された理由は、イベントの {{domxref("PromiseRejectionEvent.reason")}} プロパティを検査することでわかります。</div> +<div>{{domxref("PromiseRejectionEvent")}}インターフェイスの読み取り専用プロパティである <code><strong>promise</strong></code> は、拒否された JavaScript の {{jsxref("Promise")}} を表します。promise が拒否された理由は、イベントの {{domxref("PromiseRejectionEvent.reason")}} プロパティを検査することでわかります。</div> <h2 id="Syntax" name="Syntax">構文</h2> @@ -23,7 +23,7 @@ translation_of: Web/API/PromiseRejectionEvent/promise <h3 id="Value" name="Value">値</h3> -<p>reject(拒絶) されて、処理されていない JavaScript の{{jsxref("Promise")}}。</p> +<p>reject(拒否) されて、処理されていない JavaScript の{{jsxref("Promise")}}。</p> <h2 id="Examples" name="Examples">例</h2> diff --git a/files/ja/web/api/promiserejectionevent/promiserejectionevent/index.html b/files/ja/web/api/promiserejectionevent/promiserejectionevent/index.html index ec69ed9a7b..ba81683d0d 100644 --- a/files/ja/web/api/promiserejectionevent/promiserejectionevent/index.html +++ b/files/ja/web/api/promiserejectionevent/promiserejectionevent/index.html @@ -14,7 +14,7 @@ translation_of: Web/API/PromiseRejectionEvent/PromiseRejectionEvent --- <div>{{APIRef("HTML DOM")}}</div> -<p><code><strong>PromiseRejectionEvent()</strong></code> コンストラクタは、JavaScript の {{jsxref("Promise")}} が拒絶されたときに発火するイベントを表す {{domxref("PromiseRejectionEvent")}} を新しく生成し返します。</p> +<p><code><strong>PromiseRejectionEvent()</strong></code> コンストラクタは、JavaScript の {{jsxref("Promise")}} が拒否されたときに発火するイベントを表す {{domxref("PromiseRejectionEvent")}} を新しく生成し返します。</p> <h2 id="構文">構文</h2> @@ -32,9 +32,9 @@ translation_of: Web/API/PromiseRejectionEvent/PromiseRejectionEvent <dt><code>type</code></dt> <dd><code>PromiseRejectionEvent</code> の型名を表す文字列。これは大文字小文字を区別し、{{event("rejectionhandled", '"rejectionhandled"')}} か {{event("unhandledrejection", '"unhandledrejection"')}} のいずれかである必要がある。</dd> <dt><code>promise</code></dt> - <dd>拒絶された {{jsxref("Promise")}}。</dd> + <dd>拒否された {{jsxref("Promise")}}。</dd> <dt><code>reason</code></dt> - <dd>promise が拒絶された理由を表すいずれかの値、または {{jsxref("Object")}}。</dd> + <dd>promise が拒否された理由を表すいずれかの値、または {{jsxref("Object")}}。</dd> </dl> <h2 id="仕様">仕様</h2> diff --git a/files/ja/web/api/window/rejectionhandled_event/index.html b/files/ja/web/api/window/rejectionhandled_event/index.html index 335d40fcdb..75eccd8a77 100644 --- a/files/ja/web/api/window/rejectionhandled_event/index.html +++ b/files/ja/web/api/window/rejectionhandled_event/index.html @@ -19,7 +19,7 @@ translation_of: Web/API/Window/rejectionhandled_event --- <div>{{APIRef("HTML DOM")}}</div> -<p><span class="seoSummary"><strong><code>rejectionhandled</code></strong> イベントは、 JavaScript の {{jsxref("Promise")}} が拒絶されたものの、その後で Promise の拒絶が処理された場合にスクリプトのグローバルスコープ (ふつうは {{domxref("window")}} だが {{domxref("Worker")}} の場合もある) に送られます。</span>これは、 Promise が拒絶されたが拒絶の手助けがないときに送信される {{domxref("Window.unhandledrejection_event", "unhandledrejection")}} イベントと並行して、デバッグや一般的なアプリケーションの回復に使用できます。</p> +<p><span class="seoSummary"><strong><code>rejectionhandled</code></strong> イベントは、 JavaScript の {{jsxref("Promise")}} が拒否されたものの、その後で Promise の拒否が処理された場合にスクリプトのグローバルスコープ (ふつうは {{domxref("window")}} だが {{domxref("Worker")}} の場合もある) に送られます。</span>これは、 Promise が拒否されたが拒否の手助けがないときに送信される {{domxref("Window.unhandledrejection_event", "unhandledrejection")}} イベントと並行して、デバッグや一般的なアプリケーションの回復に使用できます。</p> <table class="properties"> <tbody> @@ -44,7 +44,7 @@ translation_of: Web/API/Window/rejectionhandled_event <h2 id="Example" name="Example">例</h2> -<p><code>rejectionhandled</code> イベントを使用して、拒絶された Promise を、拒絶された理由を添えてコンソールに出力することができます。</p> +<p><code>rejectionhandled</code> イベントを使用して、拒否された Promise を、拒否された理由を添えてコンソールに出力することができます。</p> <pre class="brush: js">window.addEventListener("rejectionhandled", event => { console.log("Promise rejected; reason: " + event.reason); diff --git a/files/ja/web/api/worker/index.html b/files/ja/web/api/worker/index.html index db0a319578..69ec3abc87 100644 --- a/files/ja/web/api/worker/index.html +++ b/files/ja/web/api/worker/index.html @@ -64,10 +64,10 @@ translation_of: Web/API/Worker <dd><code>Worker</code> オブジェクトが <a href="/ja/docs/Web/API/Web_Workers_API/Structured_clone_algorithm">シリアライズ解除</a>できないというメッセージを受け取ったときに発行されます。<br> <code><a href="/ja/docs/Web/API/Worker/onmessageerror">onmessageerror</a></code> プロパティからも利用できます。</dd> <dt><code><a href="/ja/docs/Web/API/Window/rejectionhandled_event">rejectionhandled</a></code></dt> - <dd>{{jsxref("Promise")}} が拒絶されるたびに発行されます。拒絶を処理するハンドラーがあるかどうかは問いません。<br> + <dd>{{jsxref("Promise")}} が拒否されるたびに発行されます。拒否を処理するハンドラーがあるかどうかは問いません。<br> <code><a href="/ja/docs/Web/API/WindowEventHandlers/onrejectionhandled">onrejectionhandled</a></code> イベントハンドラープロパティからも利用できます。</dd> <dt><code><a href="/ja/docs/Web/API/Window/unhandledrejection_event">unhandledrejection</a></code></dt> - <dd>拒絶を処理するハンドラーのない {{jsxref("Promise")}} が拒絶されたときに発行されます。<br> + <dd>拒否を処理するハンドラーのない {{jsxref("Promise")}} が拒否されたときに発行されます。<br> <code><a href="/ja/docs/Web/API/WindowEventHandlers/onunhandledrejection">onunhandledrejection</a></code> イベントハンドラープロパティからも利用できます。</dd> </dl> diff --git a/files/ja/web/css/user-modify/index.html b/files/ja/web/css/user-modify/index.html index 1243f13c05..854abb890e 100644 --- a/files/ja/web/css/user-modify/index.html +++ b/files/ja/web/css/user-modify/index.html @@ -72,7 +72,7 @@ user-modify: unset; <h2 id="Specifications" name="Specifications">仕様書</h2> -<p>このプロパティは仕様書で定義されていません。類似のプロパティである <code>user-focus</code> が、 <a class="external" href="http://www.w3.org/TR/2000/WD-css3-userint-20000216">CSS3 UI 仕様書の早期の草稿</a>で提案されましたが、作業グループによって拒絶されました。</p> +<p>このプロパティは仕様書で定義されていません。類似のプロパティである <code>user-focus</code> が、 <a class="external" href="http://www.w3.org/TR/2000/WD-css3-userint-20000216">CSS3 UI 仕様書の早期の草稿</a>で提案されましたが、作業グループによって拒否されました。</p> <h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの対応</h2> diff --git a/files/ja/web/events/index.html b/files/ja/web/events/index.html index 32155339ee..169f20382e 100644 --- a/files/ja/web/events/index.html +++ b/files/ja/web/events/index.html @@ -294,9 +294,9 @@ translation_of: Web/Events </tr> <tr> - <td>プロミスの拒絶</td> + <td>プロミスの拒否</td> <td> - <p>JavaScript のプロミスが拒絶されたときにグローバルスクリプトコンテキストに送信されるイベント。</p> + <p>JavaScript のプロミスが拒否されたときにグローバルスクリプトコンテキストに送信されるイベント。</p> </td> <td>イベントは <a href="/ja/docs/Web/API/Window#promise_rejection_events"><code>Window</code></a> で発行される。</td> </tr> diff --git a/files/ja/web/javascript/guide/using_promises/index.html b/files/ja/web/javascript/guide/using_promises/index.html deleted file mode 100644 index 5c2a39476b..0000000000 --- a/files/ja/web/javascript/guide/using_promises/index.html +++ /dev/null @@ -1,358 +0,0 @@ ---- -title: Promiseを使う -slug: Web/JavaScript/Guide/Using_promises -tags: - - Guide - - Intermediate - - JavaScript - - Promise - - Promises - - asynchronous - - 'l10n:priority' -translation_of: Web/JavaScript/Guide/Using_promises ---- -<div>{{jsSidebar("JavaScript Guide")}}</div> - -<p class="summary">{{jsxref("Promise")}} は非同期処理の最終的な完了もしくは失敗を表すオブジェクトです。多くの人々は既存の用意された Promise を使うことになるため、このガイドでは、Promise の作成方法の前に、関数が返す Promise の使い方から説明します。</p> - -<p>本質的に、Promise はコールバックを関数に渡すかわりに、関数が返したオブジェクトに対してコールバックを登録するようにする、というものです。</p> - -<p>例えば <code>createAudioFileAsync()</code> という非同期に音声ファイルを生成する関数を考えましょう。この関数はコンフィグオブジェクトと 2 つのコールバック関数を受け取り、片方のコールバックは音声ファイルが無事作成されたときに呼び出され、もう一つはエラーが発生したときに呼び出されます。</p> - -<p>以下のコードは <code>createAudioFileAsync()</code> を使用したものです。</p> - -<pre class="brush: js notranslate">function successCallback(result) { - console.log("Audio file ready at URL: " + result); -} - -function failureCallback(error) { - console.log("Error generating audio file: " + error); -} - -createAudioFileAsync(audioSettings, successCallback, failureCallback);</pre> - -<p>最近では関数は Promise を返し、代わりにその Promise にコールバックを登録することができます。</p> - -<p>もし <code>createAudioFileAsync()</code> が Promise を返すように書き換えられたとすれば、以下のようにシンプルに使用することができます。</p> - -<pre class="brush: js notranslate">createAudioFileAsync(audioSettings).then(successCallback, failureCallback);</pre> - -<p>これは以下のコードの短縮形です。</p> - -<pre class="brush: js notranslate">const promise = createAudioFileAsync(audioSettings); -promise.then(successCallback, failureCallback);</pre> - -<p>これを<em>非同期関数呼び出し(asynchronnous function call)</em>と呼びます。この記述方法にはいくつか利点があるので、順に説明します。</p> - -<h2 id="Guarantees" name="Guarantees">保証</h2> - -<p>旧来のコールバック渡しとは異なり、Promise では以下が保証されています。</p> - -<ul> - <li>現在の JavaScript イベントループの<a href="/ja/docs/Web/JavaScript/EventLoop#Run-to-completion">実行完了</a>より前には、コールバックが決して呼び出されない。</li> - <li>非同期処理が完了もしくは失敗した後に <code><a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/then">then()</a></code> により登録されたコールバックでも、上記のように呼び出される。</li> - <li><code><a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/then">then()</a></code> を何回も呼び出して複数のコールバックを追加してもよく、それぞれのコールバックは追加順に独立して実行される。</li> -</ul> - -<p>とはいえ、最もすぐわかる Promise の利点は <strong>Promise チェーン</strong>でしょう。</p> - -<h2 id="Chaining" name="Chaining">Promise チェーン</h2> - -<p>一般的なニーズとしては、複数の非同期処理を順番に実行し、前の処理が完了してからその結果を次の処理で使うというものがあります。これは <strong>Promise チェーン</strong>を作成することで行えます。</p> - -<p>さあ魔法の時間です。<code>then()</code> 関数は元の Promise とは別の<strong>新しい Promise</strong> を返します。</p> - -<pre class="brush: js notranslate">const promise = doSomething(); -const promise2 = promise.then(successCallback, failureCallback); -</pre> - -<p>もしくは、以下のように書いても構いません。</p> - -<pre class="brush: js notranslate">const promise2 = doSomething().then(successCallback, failureCallback); -</pre> - -<p>2 つ目の Promise は <code>doSomething()</code> の完了を表すだけではなく、渡した <code>successCallback</code> もしくは <code>failureCallback</code> の完了も表し、これらのコールバックは Promise を返すまた別の非同期関数であっても構いません。その場合、<code>promise2</code> に追加されたコールバックはいずれも Promise のキューにおいて、<code>successCallback</code> または <code>failureCallback</code> が返す Promise の後ろに追加されます。</p> - -<p>基本的に、それぞれの Promise はチェーン(連鎖)上の各非同期処理の完了を表します。</p> - -<p>昔は、複数の非同期処理を順番に実行するには、従来のコールバック地獄を作ることになりました。</p> - -<pre class="brush: js notranslate">doSomething(function(result) { - doSomethingElse(result, function(newResult) { - doThirdThing(newResult, function(finalResult) { - console.log('Got the final result: ' + finalResult); - }, failureCallback); - }, failureCallback); -}, failureCallback); -</pre> - -<p>モダンな関数を使えば、その代わりに戻り値の Promise にコールバックを付加して Promise チェーンとして記述できます。</p> - -<pre class="brush: js notranslate">doSomething() -.then(function(result) { - return doSomethingElse(result); -}) -.then(function(newResult) { - return doThirdThing(newResult); -}) -.then(function(finalResult) { - console.log('Got the final result: ' + finalResult); -}) -.catch(failureCallback); -</pre> - -<p> <code>then</code> 関数の引数はオプション(必須ではない)です。また、<code>catch(failureCallback)</code> は <code>then(null, failureCallback)</code> の短縮形です。記述には<a href="/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions">アロー関数</a>を使っても構いません。</p> - -<pre class="brush: js notranslate">doSomething() -.then(result => doSomethingElse(result)) -.then(newResult => doThirdThing(newResult)) -.then(finalResult => { - console.log(`Got the final result: ${finalResult}`); -}) -.catch(failureCallback); -</pre> - -<p><strong>重要:</strong> コールバック関数から処理結果を返すのを忘れないでください。さもないと後続のコールバック関数からその処理結果を利用することができなくなります (アロー関数を使った <code>() => x</code> は <code>() => { return x; }</code> の短縮形です)。</p> - -<h3 id="Chaining_after_a_catch" name="Chaining_after_a_catch">catch後のチェーン</h3> - -<p>失敗、つまり <code>catch</code> の後にチェーンするのも可能で、これはチェーン内の動作が失敗した後でも新しい動作を行うのに便利です。次の例を読んでください:</p> - -<pre class="brush: js notranslate">new Promise((resolve, reject) => { - console.log('Initial'); - - resolve(); -}) -.then(() => { - throw new Error('Something failed'); - - console.log('Do this'); -}) -.catch(() => { - console.log('Do that'); -}) -.then(() => { - console.log('Do this whatever happened before'); -});</pre> - -<p>これは下記のテキストを出力します:</p> - -<pre class="notranslate">Initial -Do that -Do this whatever happened before</pre> - -<p><strong>注意:</strong><q>Do this</q> のテキストは <q>Something failed</q> エラーが reject を引き起こしたため出力されないことに注意してください。</p> - -<h2 id="Error_propagation" name="Error_propagation">エラーの伝播</h2> - -<p>以前のコールバック地獄形式の記述方法では <code>failureCallback</code> を 3 回書く必要がありましたが、Promise チェーンでは <code>failureCallback</code> は 1 回で済みます。</p> - -<pre class="brush: js notranslate">doSomething() -.then(result => doSomethingElse(result)) -.then(newResult => doThirdThing(newResult)) -.then(finalResult => console.log(`Got the final result: ${finalResult}`)) -.catch(failureCallback); -</pre> - -<p>例外が発生すると、ブラウザーはチェーンをたどって <code>.catch()</code> ハンドラーか <code>onRejected</code> を探します。この振る舞いは同期的なコードの動作と非常によく類似しています。</p> - -<pre class="brush: js notranslate">try { - const result = syncDoSomething(); - const newResult = syncDoSomethingElse(result); - const finalResult = syncDoThirdThing(newResult); - console.log(`Got the final result: ${finalResult}`); -} catch(error) { - failureCallback(error); -} -</pre> - -<p>ECMAScript 2017 のシンタックスシュガー <a href="/ja/docs/Web/JavaScript/Reference/Statements/async_function"><code>async</code>/<code>await</code></a> を使えば、完全にそっくりのコードになります。</p> - -<pre class="brush: js notranslate">async function foo() { - try { - const result = await doSomething(); - const newResult = await doSomethingElse(result); - const finalResult = await doThirdThing(newResult); - console.log(`Got the final result: ${finalResult}`); - } catch(error) { - failureCallback(error); - } -} -</pre> - -<p>async/await は Promise の上に成り立っています。例えば上記の <code>doSomething()</code> はこれまでと同じ(Promise を返す)関数です。この書き方の詳細については<a href="https://developers.google.com/web/fundamentals/getting-started/primers/async-functions">こちら</a>をご覧ください。</p> - -<p>Promise は例外やプログラミングエラーを含むすべてのエラーをとらえることで、コールバック地獄の根本的な問題を解決します。これは非同期処理を合成するのに不可欠です。</p> - -<h2 id="Promise_rejection_events" name="Promise_rejection_events">Promise の失敗イベント</h2> - -<p>Promise が失敗するたびに、グローバルスコープ(通常 {{domxref("window")}} オブジェクトか、Web Worker 内ならば <a href="/ja/docs/Web/API/Worker" title="Worker インターフェイス of the Web Workers API represents a background task that can be created via script, which can send messages back to its creator."><code>Worker</code></a> か Worker ベースのインターフェイスをもつオブジェクト)に以下の 2 つのイベントのどちらかが送られます:</p> - -<dl> - <dt><a href="/ja/docs/Web/API/Window/rejectionhandled_event" title="The rejectionhandled event is sent to the script's global scope (usually window but also Worker) whenever a JavaScript Promise is rejected but after the promise rejection has been handled."><code>rejectionhandled</code></a></dt> - <dd>Promise が失敗したとき、それが <code>reject</code> 関数などによって処理されたあとに送られる。</dd> - <dt><a href="/ja/docs/Web/API/Window/unhandledrejection_event" title="The unhandledrejection event is sent to the global scope of a script when a JavaScript Promise that has no rejection handler is rejected; typically, this is the window, but may also be a Worker."><code>unhandledrejection</code></a></dt> - <dd>Promise が失敗して、ハンドラーが存在しないときに送られる。</dd> -</dl> - -<p>いずれの場合でも、イベントオブジェクト( <a href="/ja/docs/Web/API/PromiseRejectionEvent" title="PromiseRejectionEvent インターフェイス represents events which are sent to the global script context when JavaScript Promises are rejected."><code>PromiseRejectionEvent</code></a> 型)は失敗した Promise を表す <a href="/ja/docs/Web/API/PromiseRejectionEvent/promise" title="The PromiseRejectionEvent interface's promise read-only property indicates the JavaScript Promise which was rejected. You can examine the event's PromiseRejectionEvent.reason property to learn why the promise was rejected."><code>promise</code></a> プロパティと、その Promise が失敗した理由を表す <a href="/ja/docs/Web/API/PromiseRejectionEvent/reason" title="The read-only PromiseRejection property reason read-only property is any JavaScript value or Object which provides the reason passed into Promise.reject(). This in theory provides information about why the promise was rejected."><code>reason</code></a> プロパティを持ちます。</p> - -<p>これらのイベントを使えば、Promise のエラーハンドラーのフォールバックを指定することができ、また Promise を管理する際の問題をデバッグするのにも役立ちます。これらのイベントのハンドラーはコンテキストごとにグローバルであり、どこから発生したかに関わらず、すべてのエラーは同じイベントハンドラーによって処理されます。</p> - -<p>特に便利なケースとして、{{Glossary("Node.js")}} 用のコードを書いているときにプロジェクト内のモジュールで Promise が失敗しハンドルされないことがよくあります。これらは Node.js の実行環境によりコンソールに出力されます。これらの失敗を分析したりハンドラーを設定したいとき、あるいは単にコンソールがこれらで埋め尽くされないようにしたいとき、以下のように <a href="/ja/docs/Web/API/Window/unhandledrejection_event" title="The unhandledrejection event is sent to the global scope of a script when a JavaScript Promise that has no rejection handler is rejected; typically, this is the window, but may also be a Worker."><code>unhandledrejection</code></a> イベントのハンドラーを追加することができます。</p> - -<pre class="brush: js notranslate">window.addEventListener("unhandledrejection", event => { - /* ここで該当の Promise を event.promise で、失敗の理由を - event.reason で取得して調べることができます */ - - event.preventDefault(); -}, false);</pre> - -<p>イベントの <a href="/ja/docs/Web/API/Event/preventDefault" title="The Event interface's preventDefault() method tells the user agent that if the event does not get explicitly handled, its default action should not be taken as it normally would be."><code>preventDefault()</code></a> メソッドを呼び出すことによって、失敗した Promise がハンドルされないときの JavaScript の実行環境のデフォルトの動作を防ぐことができます。特に Node.js がそうですが、通常はデフォルトの動作ではエラーがコンソールに出力されます。</p> - -<p>当然ながら理想的には、これらのイベントを捨てる前に失敗した Promise を調べて、いずれもコードのバグによるものではないことを確かめるべきです。</p> - -<h2 id="Creating_a_Promise_around_an_old_callback_API" name="Creating_a_Promise_around_an_old_callback_API">古いコールバック API をラップする Promise の作成</h2> - -<p>{{jsxref("Promise")}} はコンストラクタを使って 1 から作ることもできます。これは古い API をラップする場合にのみ必要となるはずです。</p> - -<p>理想的には、すべての非同期関数は Promise を返すはずですが、残念ながら API の中にはいまだに古いやり方で成功/失敗用のコールバックを渡しているものがあります。典型的な例としては <a href="/ja/docs/Web/API/WindowTimers/setTimeout" title="The documentation about this has not yet been written; please consider contributing!"><code>setTimeout()</code></a> 関数があります。</p> - -<pre class="brush: js notranslate">setTimeout(() => saySomething("10 seconds passed"), 10*1000); -</pre> - -<p>古い形式のコールバックと Promise の混在は問題を引き起こします。というのは、<code>saySomething()</code> が失敗したりプログラミングエラーを含んでいた場合にそのエラーをとらえられないからです。<code>setTimeout</code> にその責任があります。</p> - -<p>幸いにも <code>setTimeout</code> を Promise の中にラップすることができます。ベストプラクティスは、問題のある関数を可能な限り低いレベルでラップした上で、二度と直接呼ばないようにするというものです。</p> - -<pre class="brush: js notranslate">const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); - -wait(10*1000).then(() => saySomething("10 seconds")).catch(failureCallback); -</pre> - -<p>基本的に、Promise のコンストラクタには、手動で Promise を resolve もしくは reject できるようにする実行関数を渡します。<code>setTimeout()</code> は失敗することはないので、reject は省略しました。</p> - -<h2 id="Composition" name="Composition">合成 (Composition)</h2> - -<p>{{jsxref("Promise.resolve()")}} と {{jsxref("Promise.reject()")}} はそれぞれ既に resolve もしくは reject された Promise を手動で作成するショートカットで、たまに役立つことがあります。</p> - -<p>{{jsxref("Promise.all()")}} と {{jsxref("Promise.race()")}} は同時並行で実行中の非同期処理を合成するためのツールです。</p> - -<p>以下のように複数の処理を並行に開始し、すべてが終了するのを待つことができます。</p> - -<pre class="brush: js notranslate">Promise.all([func1(), func2(), func3()]) -.then(([result1, result2, result3]) => { /* result1, result2, result3 が使える */ });</pre> - -<p>以下のように工夫すれば、逐次実行をする直列的な合成も記述することができます。</p> - -<pre class="brush: js notranslate">[func1, func2].reduce((p, f) => p.then(f), Promise.resolve()) -.then(result3 => { /* result3 が使える */ });</pre> - -<p>基本的に、これは非同期関数の配列を <code><span class="pun">Promise.resolve().then(</span><span class="pln">func1).then(</span><span class="pln">func2</span><span class="pun">).then(func3);</span></code><span class="pun"> と同等の Promise チェーンへと reduce しています。</span></p> - -<p>このような処理は以下のように、関数型プログラミングでよくある再利用可能な合成関数にすることがすることができます。</p> - -<pre class="brush: js notranslate">const applyAsync = (acc,val) => acc.then(val); -const composeAsync = (...funcs) => x => funcs.reduce(applyAsync, Promise.resolve(x));</pre> - -<p><code>composeAsync</code> 関数は任意の個数の関数を引数として受け取って、1本のパイプラインとして合成された関数を返します。この関数に渡された初期値は合成された関数を通過していきます。</p> - -<pre class="brush: js notranslate">const transformData = composeAsync(func1, func2, func3); -const result3 = transformData(data);</pre> - -<p>ECMAScript 2017 では直列的な合成は async/await でもっと単純に書くことができます。</p> - -<pre class="brush: js notranslate">let result; -for (const f of [func1, func2, func3]) { - result = await f(result); -} -/* 最終的な結果(result3)が使える */</pre> - -<h2 id="Timing" name="Timing">タイミング</h2> - -<p>想定外の事態とならないよう、たとえすでに resolve された Promise であっても、<code><a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/then">then()</a></code> に渡される関数が同期的に呼ばれることはありません。</p> - -<pre class="brush: js notranslate">Promise.resolve().then(() => console.log(2)); -console.log(1); // 1, 2 -</pre> - -<p>渡された関数は、すぐに実行されるのではなくマイクロタスクのキューに入れられます。現在のイベントループの終わりにこのキューは空になったときに、この関数が実行されます(つまりかなり早い段階です)。</p> - -<pre class="brush: js notranslate">const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); - -wait().then(() => console.log(4)); -Promise.resolve().then(() => console.log(2)).then(() => console.log(3)); -console.log(1); // 1, 2, 3, 4</pre> - -<h2 id="Nesting" name="Nesting">ネスト</h2> - -<p>単純な Promise チェーンならば、ネストは不用意な合成の結果生まれるものなので、ネストせずに平らにしておくのがベストです。<a href="#Common_mistakes">よくある間違い</a>を参照してください。</p> - -<p>ネストとは <code>catch</code> ステートメントのスコープを制限するための制御構造です。正確には、ネストされた <code>catch</code> はそのスコープ内の失敗しかキャッチせず、Promise チェーン上でスコープ外のエラーには反応しません。正しく使えばより正確にエラーからの回復ができるようになります。</p> - -<pre class="brush: js notranslate">doSomethingCritical() -.then(result => doSomethingOptional(result) - .then(optionalResult => doSomethingExtraNice(optionalResult)) - .catch(e => {})) // オプションの処理が失敗すれば無視して進める -.then(() => moreCriticalStuff()) -.catch(e => console.log("Critical failure: " + e.message));</pre> - -<p>インデントではなく外側の括弧 <code>()</code> によってオプションの処理がネストされていることに注意してください。</p> - -<p>内側の <code>catch</code> ステートメントは <code>doSomethingOptional()</code> と <code>doSomethingExtraNice()</code> からの失敗だけをキャッチし、キャッチしたあと <code>moreCriticalStuff()</code> へと処理が続きます。重要なのは、もし <code>doSomethingCritical()</code> が失敗したらそのエラーは最後の <code>catch</code> によってだけキャッチされるということです。</p> - -<h2 id="Common_mistakes" name="Common_mistakes">よくある間違い</h2> - -<p>Promise チェーンを合成するときは以下のようなよくある間違いに気をつける必要があります。以下の例にいくつかの間違いが含まれています。</p> - -<pre class="brush: js example-bad notranslate">// 悪い例。間違いを 3 つ見つけてください。 - -doSomething().then(function(result) { - doSomethingElse(result) // 内側のチェーンから Promise を返していない + 不必要なネスト - .then(newResult => doThirdThing(newResult)); -}).then(() => doFourthThing()); -// チェーンの最後を catch で終わらせていない -</pre> - -<p>最初の間違いは適切にチェーンを構成できていないことです。これは、新しい Promise を作成したがそれを返すのを忘れているときに起きます。結果としてチェーンは壊れ、2 つのチェーンが独立に実行されることになります。これはつまり <code>doFourthThing()</code> は <code>doSomethingElse()</code> や <code>doThirdThing()</code> の終了を待たないことになり、おそらく意図せず並行して実行されることになります。別々のチェーンでは別々のエラーハンドリングが行われるため、キャッチされないエラーが発生することになります。</p> - -<p>2 つ目の間違いは不必要にネストしていることであり、1 つめの間違いを可能にしているものでもあります。ネストするということは内側のエラーハンドラーが制限されるということであり、もしこれが意図していないものであれば、エラーがキャッチされないということが起こりえます。これの変化形で <a href="https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it">Promise コンストラクターアンチパターン</a>というものがあり、ネストに加えて、Promise を既に使用しているコードを不必要な Promise コンストラクターでラップするというものです。</p> - -<p>3 つ目の間違いはチェーンを <code>catch</code> で終わらせていないことです。ほとんどのブラウザーではそのようなチェーンは Promise の失敗がキャッチされないことになります。</p> - -<p>よい経験則としては、Promise チェーンは常に <code>return</code> するか <code>catch</code> で終わらせ、新しい Promise を得るたびにすぐに <code>return</code> してチェーンを平らにすることです。</p> - -<pre class="brush: js example-good notranslate">doSomething() -.then(function(result) { - return doSomethingElse(result); -}) -.then(newResult => doThirdThing(newResult)) -.then(() => doFourthThing()) -.catch(error => console.log(error)); -</pre> - -<p><code>() => x</code> は <code>() => { return x; }</code> の短縮形であることに注意してください。</p> - -<p>これで適切なエラーハンドリングがされた 1本のチェーンができました。</p> - -<p><a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/async_function"><code>async</code>/<code>await</code></a> を使えば、すべてではないにしてもほとんどの問題は解決しますが、このシンタックスで最もよくある間違いが <code><a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/async_function">await</a></code> キーワードを忘れることであるという欠点があります。</p> - -<h2 id="When_promises_and_tasks_collide" name="When_promises_and_tasks_collide">Promises とタスクが衝突するとき</h2> - -<p>(イベントとコールバックのような) Promise とタスクが予知できない順序で発火するような状況に陥る場合、Promise が条件付きで作成されて Promise の状態をチェックしたり帳尻合わせしたりするマイクロタスクを利用できることがあります。</p> - -<p>マイクロタスクでこの問題を解決できると考えたなら、<a href="/ja/docs/Web/API/HTML_DOM_API/Microtask_guide">microtask guide</a> を見て、関数をマイクロタスクでキューに入れる <a href="/ja/docs/Web/API/WindowOrWorkerGlobalScope/queueMicrotask" title="The queueMicrotask() method, which is exposed on the Window or Worker interface, queues a microtask to be executed at a safe time prior to control returning to the browser's event loop."><code>queueMicrotask()</code></a> の使い方を学んでください。</p> - -<h2 id="See_also" name="See_also">関連項目</h2> - -<ul> - <li>{{jsxref("Promise.then()")}}</li> - <li><a href="/ja/docs/Web/JavaScript/Reference/Statements/async_function"><code>async</code>/<code>await</code></a></li> - <li><a href="http://promisesaplus.com/">Promises/A+ specification</a></li> - <li><a href="https://medium.com/@ramsunvtech/promises-of-promise-part-1-53f769245a53">Venkatraman.R - JS Promise (Part 1, Basics)</a></li> - <li><a href="https://medium.com/@ramsunvtech/js-promise-part-2-q-js-when-js-and-rsvp-js-af596232525c#.dzlqh6ski">Venkatraman.R - JS Promise (Part 2 - Using Q.js, When.js and RSVP.js)</a></li> - <li><a href="https://tech.io/playgrounds/11107/tools-for-promises-unittesting/introduction">Venkatraman.R - Tools for Promises Unit Testing</a></li> - <li><a href="http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html">Nolan Lawson: We have a problem with promises — Common mistakes with promises</a></li> -</ul> - -<p>{{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Iterators_and_Generators")}}</p> diff --git a/files/ja/web/javascript/guide/using_promises/index.md b/files/ja/web/javascript/guide/using_promises/index.md new file mode 100644 index 0000000000..35b791ab66 --- /dev/null +++ b/files/ja/web/javascript/guide/using_promises/index.md @@ -0,0 +1,410 @@ +--- +title: プロミスの使用 +slug: Web/JavaScript/Guide/Using_promises +tags: + - Guide + - Intermediate + - JavaScript + - Promise + - Promises + - asynchronous + - l10n:priority +translation_of: Web/JavaScript/Guide/Using_promises +--- +{{jsSidebar("JavaScript Guide")}}{{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Iterators_and_Generators")}} + +プロミス ({{jsxref("Promise")}}) は、非同期処理の最終的な完了もしくは失敗を表すオブジェクトです。多くの人々は既存の用意されたプロミスを使うことになるため、このガイドでは、プロミスの作成方法の前に、関数が返すプロミスの使い方から説明します。 + +基本的に、プロミスはコールバックを関数に渡すかわりに、関数が返したオブジェクトに対してコールバックを登録するようにするというものです。 + +例えば、`createAudioFileAsync()` という非同期に音声ファイルを生成する関数を考えてみましょう。この関数は構成オブジェクトと 2 つのコールバック関数を受け取り、片方のコールバックは音声ファイルが無事作成されたときに呼び出され、もう一つはエラーが発生したときに呼び出されるとします。 + +以下のコードは `createAudioFileAsync()` を使用したものです。 + +```js +function successCallback(result) { + console.log("Audio file ready at URL: " + result); +} + +function failureCallback(error) { + console.error("Error generating audio file: " + error); +} + +createAudioFileAsync(audioSettings, successCallback, failureCallback); +``` + +`createAudioFileAsync()` をプロミスを返すように書き換えると、コールバックを次のように割り当てることができます。 + +```js +createAudioFileAsync(audioSettings).then(successCallback, failureCallback); +``` + +この記述方法にはいくつか利点があるので、順に説明します。 + +## 保証 + +旧来のコールバック*渡し*とは異なり、プロミスでは以下のことが保証されています。 + +- [`then()`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) によって追加されたコールバックは、現在の JavaScript イベントループの[現在の処理の完了](/ja/docs/Web/JavaScript/EventLoop#run-to-completion)より前には決して呼び出されません。 +- これらのコールバックは、プロミスが表す非同期操作が成功または失敗した*後*に追加したとしても呼び出されます。 +- [`then()`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) を複数回呼び出すことで、複数のコールバックを追加することができます。それぞれのコールバックは追加した順番に実行されます。 + +プロミスを使用する最大の利点の一つは**連鎖**でしょう。 + +## 連鎖 + +よくあるニーズはとして、 2 つ以上の非同期操作を連続して実行し、前の操作が成功したときに、前のステップの結果を使って後続の各操作を開始するというものがあります。プロミス連鎖を作成することで、これを実現することができます。 + +さあ魔法の時間です。`then()` 関数は元のプロミスとは別の**新しいプロミス**を返します。 + +```js +const promise = doSomething(); +const promise2 = promise.then(successCallback, failureCallback); +``` + +もしくは、以下のように書いても構いません。 + +```js +const promise2 = doSomething().then(successCallback, failureCallback); +``` + +2 つ目のプロミス (`promise2`) は `doSomething()` の完了を表すだけではなく、渡した `successCallback` もしくは `failureCallback` の完了も表し、これらのコールバックはプロミスを返すまた別の非同期関数であっても構いません。その場合、`promise2` に追加されたコールバックはいずれもプロミスのキューにおいて、`successCallback` または `failureCallback` が返すプロミスの後ろに追加されます。 + +基本的に、それぞれのプロミスは連鎖上にある個々の非同期の段階の完了を表します。 + +昔は、複数の非同期処理を順番に実行するには、従来の恐ろしいコールバック地獄を作ることになりました。 + +```js +doSomething(function(result) { + doSomethingElse(result, function(newResult) { + doThirdThing(newResult, function(finalResult) { + console.log('Got the final result: ' + finalResult); + }, failureCallback); + }, failureCallback); +}, failureCallback); +``` + +現在の機能を使えば、その代わりに返却されたプロミスににコールバックを付加してプロミス連鎖として記述できます。 + +```js +doSomething() +.then(function(result) { + return doSomethingElse(result); +}) +.then(function(newResult) { + return doThirdThing(newResult); +}) +.then(function(finalResult) { + console.log('Got the final result: ' + finalResult); +}) +.catch(failureCallback); +``` + +`then` 関数の引数は任意であり、また、 `catch(failureCallback)` は `then(null, failureCallback)` の短縮形です。記述には[アロー関数](/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions)を使っても構いません。 + +```js +doSomething() +.then(result => doSomethingElse(result)) +.then(newResult => doThirdThing(newResult)) +.then(finalResult => { + console.log(`Got the final result: ${finalResult}`); +}) +.catch(failureCallback); +``` + +**重要:** コールバック関数から処理結果を返すのを忘れないでください。さもないと後続のコールバック関数からその処理結果を利用することができなくなります (アロー関数を使った `() => x` は `() => { return x; }` の短縮形です)。 + +### catch の後の連鎖 + +失敗、つまり `catch` の後に連鎖することも可能で、これは連鎖内の動作が失敗した後でも新しい動作を行うのに便利です。次の例を読んでください。 + +```js +new Promise((resolve, reject) => { + console.log('Initial'); + + resolve(); +}) +.then(() => { + throw new Error('Something failed'); + + console.log('Do this'); +}) +.catch(() => { + console.error('Do that'); +}) +.then(() => { + console.log('Do this, no matter what happened before'); +}); +``` + +これは下記のテキストを出力します。 + +```plain +Initial +Do that +Do this, no matter what happened before +``` + +**注意:** "Do this" のテキストは "Something failed" エラーが拒否をを引き起こしたため出力されないことに注意してください。 + +## エラーの伝播 + +以前のコールバック地獄形式の記述方法では `failureCallback` を 3 回書く必要がありましたが、プロミス連鎖では 1 回で済みます。 + +```js +doSomething() +.then(result => doSomethingElse(result)) +.then(newResult => doThirdThing(newResult)) +.then(finalResult => console.log(`Got the final result: ${finalResult}`)) +.catch(failureCallback); +``` + +例外が発生すると、ブラウザーは連鎖をたどって `.catch()` ハンドラーか `onRejected` を探します。この動作は同期的なコードの動作ととてもよく似ています。 + +```js +try { + const result = syncDoSomething(); + const newResult = syncDoSomethingElse(result); + const finalResult = syncDoThirdThing(newResult); + console.log(`Got the final result: ${finalResult}`); +} catch(error) { + failureCallback(error); +} +``` + +ECMAScript 2017 の糖衣構文 [`async`/`await`](/ja/docs/Web/JavaScript/Reference/Statements/async_function) を使えば、非同期コードとそっくりになります。 + +```js +async function foo() { + try { + const result = await doSomething(); + const newResult = await doSomethingElse(result); + const finalResult = await doThirdThing(newResult); + console.log(`Got the final result: ${finalResult}`); + } catch(error) { + failureCallback(error); + } +} +``` + +async/await はプロミスの上に成り立っています。例えば上記の `doSomething()` は以前と同じ関数です。の書き方の詳細については[こちら](https://developers.google.com/web/fundamentals/getting-started/primers/async-functions)をご覧ください。 + +プロミスは例外やプログラミングエラーを含むすべてのエラーをとらえることで、コールバック地獄の根本的な問題を解決します。これは非同期処理を合成するのに不可欠です。 + +## プロミスの拒否イベント + +プロミスが拒否されるたびに、グローバルスコープ (通常は {{domxref("window")}} オブジェクトか、ウェブワーカー内ならば [`Worker`](/ja/docs/Web/API/Worker "Worker は Web Workers API のインターフェイスで、作成主に対してメッセージを送ることができる、スクリプトを通じて生成されたバックグラウンドタスクを表します。") かワーカーベースのインターフェイスをもつオブジェクト) に以下の 2 つのイベントのどちらかが送られます。 + +- [`rejectionhandled`](/ja/docs/Web/API/Window/rejectionhandled_event "rejectionhandled イベントは、 JavaScript の Promise が拒否されたものの、その後でそのプロミスの拒否が処理された場合にスクリプトのグローバルスコープ (ふつうは window だが Worker の場合もある) に送られます。") + - : プロミスが拒否されたとき、実行者の `reject` 関数によって拒否が処理された後に送られます。 +- [`unhandledrejection`](/ja/docs/Web/API/Window/unhandledrejection_event "unhandledrejection イベントは、 JavaScript の拒否ハンドラーを持たない Promise が拒否されたときにスクリプトのグローバルスコープに送られます。 通常、これは window ですが、 Worker であることもあります。") + - : プロミスが拒否されたものの、拒否ハンドラーが利用できない場合に送られます。 + +いずれの場合でも、この ([`PromiseRejectionEvent`](/ja/docs/Web/API/PromiseRejectionEvent "PromiseRejectionEvent インターフェイスは、 JavaScript の Promise が拒否されたときにグローバルスクリプトコンテキストに送信されるイベントを表します。") 型のイベントは、拒否されたプロミスを示す [`promise`](/ja/docs/Web/API/PromiseRejectionEvent/promise "PromiseRejectionEvent インターフェイスの読み取り専用プロパティである promise は、拒否された JavaScript の Promise を表します。そのプロミスが拒絶された理由は、イベントの PromiseRejectionEvent.reason プロパティを検査するとわかります。") プロパティと、そのプロミスが失敗した理由を表す [`reason`](/ja/docs/Web/API/PromiseRejectionEvent/reason "PromiseRejectionEventの reason 読み取り専用プロパティは、Promise.reject() に渡される理由を提供する任意の JavaScript 値、または Object です。理論的にはプロミスが拒否された理由についての情報を提供します。") プロパティを持ちます。 + +これらのイベントを使えば、プロミスのエラー処理のフォールバックを指定することができ、またプロミスを管理する際の問題をデバッグするのにも役立ちます。これらのハンドラーはコンテキストごとにグローバルであり、発生元に関わらず、すべてのエラーが同じイベントハンドラーによって処理されます。 + +特に便利なケースとして、 [Node.js](/ja/docs/Glossary/Node.js) 用のコードを書いているときに、プロジェクト内のモジュールでプロミスが拒否され処理されないことがよくあります。これらは Node.js の実行環境ではコンソールに出力されます。次のようにして Node.js に `unhandledRejection` イベントのハンドラーを追加することで、これを捕えて分析したり、自分のコードで処理したり—または、出力が埋め尽くされないようにしたいだけの場合も—することができます。 + +```js +process.on("unhandledRejection", (reason, promise) => { + /* ここにコードを追加することで、 "promise" および "reason" の値を + * 検査することができます。 */ +}); +``` + +Node.js では、エラーがコンソールに記録されること (そうしないと発生する既定のアクション) を防ぐには、 `process.on()` リスナーを追加するだけで十分です。ブラウザーの実行環境の [`preventDefault()`](/ja/docs/Web/API/Event/preventDefault) のようなことを行う必要はありません。 + +しかし、 `process.on` リスナーを追加しても、その中に拒否されたプロミスを処理するコードがなければ、プロミスは床に落ちて暗黙に無視されてしまいます。そのため、できればリスナー内にコードを追加して、拒否されたプロミスをそれぞれ検証し、実際のコードのバグが原因ではないことを確認してください。 + +## 古いコールバック API をラップする Promise の作成 + +{{jsxref("Promise")}} はコンストラクターを使って 1 から生成すこともできます。これが必要になるのは古い API をラップする場合のみでしょう。 + +理想的には、すべての非同期関数はプロミスを返すはずですが、残念ながら API の中にはいまだに古いやり方で成功/失敗用のコールバックを渡しているものがあります。顕著な例としては [`setTimeout()`](/ja/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) 関数があります。 + +```js +setTimeout(() => saySomething("10 seconds passed"), 10*1000); +``` + +古い様式であるコールバックとプロミスの混在は問題を引き起こします。というのは、`saySomething()` が失敗したりプログラミングエラーを含んでいた場合に、そのエラーをとらえられないからです。`setTimeout` にその責任があります。 + +幸いにも `setTimeout` をプロミスの中にラップすることができます。良いやり方は、問題のある関数をできる限り低い水準でラップした上で、直接呼び出さないようにすることです。 + +```js +const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); + +wait(10*1000).then(() => saySomething("10 seconds")).catch(failureCallback); +``` + +基本的に、プロミスのコンストラクターには、手動でプロミスを解決または拒否できるようにする実行関数を渡します。実際には `setTimeout()` は失敗することがないので、この場合は拒否を省略しました。 + +## 合成 + +{{jsxref("Promise.resolve()")}} と {{jsxref("Promise.reject()")}} は、それぞれ既に解決または拒否されたプロミスを手動で生成するショートカットです。たまに役立つことがあります。 + +{{jsxref("Promise.all()")}} と {{jsxref("Promise.race()")}} は並行して実行されている非同期処理を合成するためのツールです。 + +以下のように複数の処理を並行に開始し、すべてが終了するのを待つことができます。 + +```js +Promise.all([func1(), func2(), func3()]) +.then(([result1, result2, result3]) => { /* result1, result2, result3 を使用 */ }); +``` + +以下のように工夫すれば、逐次実行をする直列的な合成も記述することができます。 + +```js +[func1, func2, func3].reduce((p, f) => p.then(f), Promise.resolve()) +.then(result3 => { /* result3 を使用 */ }); +``` + +基本的に、これは非同期関数の配列を `Promise.resolve().then(func1).then(func2).then(func3);` と同等のプロミス連鎖へとまとめます。 + +これは、関数型プログラミングでよく見られる、再利用可能な合成関数にすることができます。 + +```js +const applyAsync = (acc,val) => acc.then(val); +const composeAsync = (...funcs) => x => funcs.reduce(applyAsync, Promise.resolve(x)); +``` + +`composeAsync()` 関数は、任意の数の関数を引数として受け取り、合成パイプラインに渡される初期値を受け取る新しい関数を返します。 + +```js +const transformData = composeAsync(func1, func2, func3); +const result3 = transformData(data); +``` + +ECMAScript 2017 では、直列的な合成は async/await でもっと単純に書くことができます。 + +```js +let result; +for (const f of [func1, func2, func3]) { + result = await f(result); +} +/* 最終的な結果 (すなわち result3) を使用 */ +``` + +## タイミング + +想定外の事態とならないよう、たとえすでに解決されたプロミスであっても、[`then()`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) に渡された関数が同期的に呼び出されることはありません。 + +```js +Promise.resolve().then(() => console.log(2)); +console.log(1); // 1, 2 +``` + +渡された関数はすぐに実行されるのではなく、マイクロタスクのキューに入れられます。後で (生成した関数が終了し、 JavaScript の実行スタックが空になってから)、イベントループに制御が戻される直前、つまりかなり早い段階で実行されます。 + +```js +const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); + +wait(0).then(() => console.log(4)); +Promise.resolve().then(() => console.log(2)).then(() => console.log(3)); +console.log(1); // 1, 2, 3, 4 +``` + +#### タスクキューとマイクロタスク + +プロミスのコールバックは[マイクロタスク](/ja/docs/Web/API/HTML_DOM_API/Microtask_guide)として処理され、 [`setTimeout()`](/ja/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) コールバックはタスクキューとして扱われます。 + +```js +const promise = new Promise(function(resolve, reject) { + console.log("Promise callback"); + resolve(); +}).then(function(result) { + console.log("Promise callback (.then)"); +}); + +setTimeout(function() { + console.log("event-loop cycle: Promise (fulfilled)", promise) +}, 0); + +console.log("Promise (pending)", promise); +``` + +上記のコードの出力は次の通りです。 + +```plain +Promise callback +Promise (pending) Promise {<pending>} +Promise callback (.then) +event-loop cycle: Promise (fulfilled) Promise {<fulfilled>} +``` + +詳しくは、[タスクとマイクロタスク](/ja/docs/Web/API/HTML_DOM_API/Microtask_guide/In_depth#tasks_vs_microtasks)を参照してください。 + +## 入れ子 + +単純なプロミス連鎖は、不注意な構成の結果として入れ子が発生することがあるので、入れ子にせずに平らに保つのがベストです。[よくある間違い](#common_mistakes)を参照してください。 + +入れ子は、`catch` 文の範囲を制限するための制御構造です。具体的には、入れ子になった `catch` は、そのスコープ以下のエラーのみを捕捉し、入れ子になったスコープの外側にある連鎖の上位のエラーは捕捉しません。正しく使用すれば、エラー回復の精度が高まります。 + +```js +doSomethingCritical() +.then(result => doSomethingOptional(result) + .then(optionalResult => doSomethingExtraNice(optionalResult)) + .catch(e => {})) // オプションの処理が失敗すれば無視して進める +.then(() => moreCriticalStuff()) +.catch(e => console.error("Critical failure: " + e.message)); +``` + +インデントではなく外側の `(` および `)` によってオプションの処理が入れ子になっていることに注意してください。 + +内側の `catch` ステートメントは `doSomethingOptional()` と `doSomethingExtraNice()` からの失敗だけを捕捉し、捕捉したあと `moreCriticalStuff()` へと処理が続きます。重要なのは、もし `doSomethingCritical()` が失敗したらそのエラーは最後 (外側) の `catch` によってだけ捕捉されるということです。 + +<h2 id="Common_mistakes">よくある間違い</h2> + +Promise 連鎖を合成するときは以下のようなよくある間違いに気をつける必要があります。以下の例にいくつかの間違いが含まれています。 + +```js example-bad +// 悪い例。間違いを 3 つ見つけてください。 + +doSomething().then(function(result) { + doSomethingElse(result) // 内側の連鎖でプロミスを返していない + 不必要な入れ子 + .then(newResult => doThirdThing(newResult)); +}).then(() => doFourthThing()); +// 連鎖の最後で catch を忘れている +``` + +最初の間違いは適切に連鎖を構成できていないことです。これは、新しいプロミスを作成したものの、それを返すのを忘れているときに起きます。結果として連鎖は壊れ、2 つの連鎖が独立して実行されることになります。これはつまり `doFourthThing()` は `doSomethingElse()` や `doThirdThing()` の終了を待たないことになり、おそらく意図せず並行して実行されることになります。別々の連鎖では別々のエラーハンドリングが行われるため、捕捉されないエラーが発生することになります。 + +2 つ目の間違いは不必要に入れ子にしていることであり、1 つ目の間違いを発生させているものでもあります。入れ子にするということは内側のエラーハンドラーがのスコープが制限されるということであり、もしこれが意図していないものであれば、エラーが捕捉されない場合があります。これの変化形で[プロミスのコンストラクターアンチパターン](https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it)というものがあり、ネストに加えて、プロミスを既に使用しているコードを不必要なプロミスのコンストラクターでラップするというものです。 + +3 つ目の間違いは連鎖を `catch` で終わらせていないことです。プロミス連鎖が終わっていないと、多くのブラウザーでは、プロミスの拒否が捕捉されないことになります。 + +常識的には、常にプロミス連鎖を返すか終了させるかのどちらかで、新しいプロミスを受け取ったらすぐに返すようにして、物事をフラットにするのが良いでしょう。 + +```js example-good +doSomething() +.then(function(result) { + return doSomethingElse(result); +}) +.then(newResult => doThirdThing(newResult)) +.then(() => doFourthThing()) +.catch(error => console.error(error)); +``` + +`() => x` は `() => { return x; }` の短縮形であることに注意してください。 + +これで適切なエラー処理が行われる 1 本の連鎖ができました。 + +[`async`/`await`](/ja/docs/Web/JavaScript/Reference/Statements/async_function) を使えば、すべてではないにしてもほとんどの問題は解決します。それと引き換えに、この構文で最もよくある間違いが [`await`](/ja/docs/Web/JavaScript/Reference/Statements/async_function) キーワードを忘れることです。 + +## プロミスとタスクが衝突するとき + +プロミスとタスク (イベントやコールバックなど) が予測不可能な順序で発行されている状況に遭遇した場合、マイクロタスクを使用して状態をチェックしたり、プロミスが条件付きで作成されている場合にプロミスのバランスを取ったりすることが有益である可能性があります。 + +マイクロタスクがこの問題の解決に役立つと思われる場合は、[マイクロタスクガイド](/ja/docs/Web/API/HTML_DOM_API/Microtask_guide)で [`queueMicrotask()`](/en-US/docs/Web/API/WindowOrWorkerGlobalScope/queueMicrotask "queueMicrotask() メソッドは、Window または Worker インターフェースで公開されており、ブラウザーのイベントループに制御が戻る前の安全なタイミングで実行されるマイクロタスクをキューに入れます。") を使用して関数をマイクロタスクとしてキューに入れる方法について詳しく説明しています。 + +## 関連情報 + +- {{jsxref("Promise.then()")}} +- [`async`/`await`](/en-US/docs/Web/JavaScript/Reference/Statements/async_function) +- [Promises/A+ specification](https://promisesaplus.com/) +- [Venkatraman.R - JS Promise (Part 1, Basics)](https://medium.com/@ramsunvtech/promises-of-promise-part-1-53f769245a53) +- [Venkatraman.R - JS Promise (Part 2 - Using Q.js, When.js and RSVP.js)](https://medium.com/@ramsunvtech/js-promise-part-2-q-js-when-js-and-rsvp-js-af596232525c#.dzlqh6ski) +- [Venkatraman.R - Tools for Promises Unit Testing](https://tech.io/playgrounds/11107/tools-for-promises-unittesting/introduction) +- [Nolan Lawson: We have a problem with promises — Common mistakes with promises](https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html) + +{{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Iterators_and_Generators")}} diff --git a/files/ja/web/javascript/reference/global_objects/escape/index.html b/files/ja/web/javascript/reference/global_objects/escape/index.html deleted file mode 100644 index 046fd2667b..0000000000 --- a/files/ja/web/javascript/reference/global_objects/escape/index.html +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: escape() -slug: Web/JavaScript/Reference/Global_Objects/escape -tags: - - Deprecated - - JavaScript - - Method - - メソッド - - 非推奨 -translation_of: Web/JavaScript/Reference/Global_Objects/escape ---- -<div>{{jsSidebar("Objects")}}</div> - -<div class="warning"><strong>警告:</strong> <code>escape()</code> は厳密には非推奨ではありませんが (「ウェブ標準から削除された」という意味で)、ECMA-262 標準の <a href="https://www.ecma-international.org/ecma-262/9.0/index.html#sec-additional-ecmascript-features-for-web-browsers">Annex B</a> で定義されており、その導入部には次のように書かれています。 - -<blockquote>… この付属書で規定されているすべての言語機能と動作は、1つ以上の望ましくない特性を持ち、レガシーな使用例がない場合は、この仕様から削除されます。…<br> -… プログラマは、新しい ECMAScript コードを書くときに、これらの機能や動作の存在を使用したり、仮定したりしてはいけません。…</blockquote> -</div> - -<p><span class="seoSummary">The <code><strong>escape()</strong></code> 関数は、特定の文字を16進数のエスケープシーケンスで置き換えた新しい文字列を計算します。</span></p> - -<div class="blockIndicator note"> -<p><strong>メモ:</strong> この関数は、主に URL クエリ (URL の <code>?</code> に続く部分) に使われていました。 — "<code>\x<var>HH</var></code>" の形式を使用して、ふつうの文字列リテラルをエスケープするためのものでは<em>ありません</em>。 (HHは2桁の16進数であり、より高い面の Unicode 文字には「\xHH\xHHxHH」という形式が使われます。)</p> - -<p>文字列リテラル内のエスケープされた文字は、 <code>\x</code> を <code>%</code> に置き換えてから、 <code>decodeURIComponent()</code> 関数を使用することで展開することができます。</p> -</div> - -<h2 id="Syntax" name="Syntax">構文</h2> - -<pre class="syntaxbox">escape(<var>str</var>)</pre> - -<h3 id="Parameters" name="Parameters">引数</h3> - -<dl> - <dt><code><var>str</var></code></dt> - <dd>エンコードする文字列。</dd> -</dl> - -<h3 id="Return_value" name="Return_value">返値</h3> - -<p>特定の文字がエスケープされた新しい文字列。</p> - -<h2 id="Description" name="Description">解説</h2> - -<p><code>escape</code> 関数は<em>グローバルオブジェクト</em>のプロパティです。特殊文字は <code>@*_+-./</code> 以外の文字が符号化されます。</p> - -<p>文字の16進数形式として、文字コードの値が <code>0xFF</code> 以下になる文字は 2 桁のエスケープシーケンス <code>%<var>xx</var></code> が、それ以上の場合は 4 桁のエスケープシーケンス <code>%<strong>u</strong><var>xxxx</var></code><code>%<strong>u</strong><var>xxxx</var></code> が使われます。</p> - -<h2 id="Examples" name="Examples">例</h2> - -<pre class="brush: js">escape('abc123'); // "abc123" -escape('äöü'); // "%E4%F6%FC" -escape('ć'); // "%u0107" - -// 特殊文字 -escape('@*_+-./'); // "@*_+-./"</pre> - -<h2 id="Specifications" name="Specifications">仕様書</h2> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">仕様書</th> - </tr> - </thead> - <tbody> - <tr> - <td>{{SpecName('ESDraft', '#sec-escape-string', 'escape')}}</td> - </tr> - </tbody> -</table> - -<div class="hidden">リファレンスページにポリフィルを追加しないでください。詳しくは、 <a href="https://discourse.mozilla.org/t/mdn-rfc-001-mdn-wiki-pages-shouldnt-be-a-distributor-of-polyfills/24500">https://discourse.mozilla.org/t/mdn-rfc-001-mdn-wiki-pages-shouldnt-be-a-distributor-of-polyfills/24500</a> を参照してください。</div> - -<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2> - -<p>{{Compat("javascript.builtins.escape")}}</p> - -<h2 id="See_also" name="See_also">関連情報</h2> - -<ul> - <li>{{jsxref("encodeURI")}}</li> - <li>{{jsxref("encodeURIComponent")}}</li> - <li>{{jsxref("unescape")}}</li> -</ul> diff --git a/files/ja/web/javascript/reference/global_objects/escape/index.md b/files/ja/web/javascript/reference/global_objects/escape/index.md new file mode 100644 index 0000000000..5546f806fd --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/escape/index.md @@ -0,0 +1,70 @@ +--- +title: escape() +slug: Web/JavaScript/Reference/Global_Objects/escape +tags: + - Deprecated + - JavaScript + - メソッド +browser-compat: javascript.builtins.escape +translation_of: Web/JavaScript/Reference/Global_Objects/escape +--- +{{jsSidebar("Objects")}} + +> **Warning:** `escape()` は厳密には (「ウェブ標準から削除された」という意味で) 非推奨ではありませんが、ECMA-262 標準の [Annex B](https://www.ecma-international.org/ecma-262/9.0/index.html#sec-additional-ecmascript-features-for-web-browsers) で定義されており、その導入部には次のように書かれています。 +> +> > … この付録で規定されているすべての言語機能と動作は、 1 つ以上の望ましくない特性を持ち、レガシーな使用例がない場合は、この仕様から削除されます。… +> … プログラマーは、新しい ECMAScript のコードを書くときに、これらの機能や動作の存在を使用したり、仮定したりしてはいけません。… + +The **`escape()`** 関数は、特定の文字を 16 進数のエスケープシーケンスで置き換えた新しい文字列を計算します。 + +> **Note:** この関数は、主に URL クエリー (URL の `?` に続く部分) に使われていました。 — "`\xHH`" の形式を使用して、ふつうの文字列リテラルをエスケープするためのものでは*ありません*。 (HH は 2 桁の 16 進数であり、より高い面の Unicode 文字には「\xHH\xHHxHH」という形式が使われます。) +> +> 文字列リテラル内のエスケープされた文字は、 `\x` を `%` に置き換えてから、 `decodeURIComponent()` 関数を使用することで展開することができます。 + +## 構文 + +```js +escape(str) +``` + +### 引数 + +- `str` + - : エンコードする文字列。 + +### 返値 + +特定の文字がエスケープされた新しい文字列。 + +## 解説 + +`escape` 関数は*グローバルオブジェクト*のプロパティです。特殊文字は `@*_+-./` 以外の文字が符号化されます。 + +文字の 16 進数形式として、文字コードの値が `0xFF` 以下になる文字は 2 桁のエスケープシーケンス `%xx` が、それ以上の場合は 4 桁のエスケープシーケンス `%uxxxx` が使われます。 + +## 例 + +### escape の使用 + +```js +escape('abc123'); // "abc123" +escape('äöü'); // "%E4%F6%FC" +escape('ć'); // "%u0107" + +// 特殊文字 +escape('@*_+-./'); // "@*_+-./" +``` + +## 仕様書 + +{{Specifications}} + +## ブラウザーの互換性 + +{{Compat}} + +## 関連情報 + +- {{jsxref("encodeURI")}} +- {{jsxref("encodeURIComponent")}} +- {{jsxref("unescape")}} diff --git a/files/ja/web/javascript/reference/global_objects/promise/any/index.html b/files/ja/web/javascript/reference/global_objects/promise/any/index.html deleted file mode 100644 index bca62a9a74..0000000000 --- a/files/ja/web/javascript/reference/global_objects/promise/any/index.html +++ /dev/null @@ -1,152 +0,0 @@ ---- -title: Promise.any() -slug: Web/JavaScript/Reference/Global_Objects/Promise/any -tags: - - Experimental - - JavaScript - - Method - - NeedsCompatTable - - Promise - - Reference - - プロミス - - メソッド - - 実験的 -translation_of: Web/JavaScript/Reference/Global_Objects/Promise/any ---- -<div>{{JSRef}}</div> - -<p><code>Promise.any()</code> は {{JSxRef("Promise")}} オブジェクトの反復可能オブジェクトを受け取り、反復可能オブジェクトの中にあるプロミスの一つが満足するとすぐに、そのプロミスの値で解決される単一のプロミスを返します。反復可能オブジェクトの中に満足可能なプロミスがない場合 (与えられたプロミスがすべて拒否された場合)、返されたプロミスは {{JSxRef("AggregateError")}} という、個々のエラーをグループ化した {{JSxRef("Error")}} の新しいサブクラスで拒否されます。本質的には、このメソッドは {{JSxRef("Promise.all()")}} の反対です。</p> - -<div class="blockIndicator warning"> -<p><strong>警告!</strong> <code>Promise.any()</code> メソッドは実験的であり、すべてのブラウザーが対応しているわけではありません。現在は <a href="https://github.com/tc39/proposal-promise-any" rel="external">TC39 Candidate stage (Stage 4)</a> にあります。</p> -</div> - -<h2 id="Syntax" name="Syntax">構文</h2> - -<pre class="notranslate">Promise.any(<var>iterable</var>);</pre> - -<h3 id="Parameters" name="Parameters">引数</h3> - -<dl> - <dt><code><var>iterable</var></code></dt> - <dd><a href="/ja/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol">反復可能</a>オブジェクト、例えば {{JSxRef("Array")}} です。</dd> -</dl> - -<h3 id="Return_value" name="Return_value">返値</h3> - -<ul> - <li>渡された <var>iterable</var> が空の場合は、<strong>解決済みの</strong> {{JSxRef("Promise")}}。</li> - <li>渡された <var>iterable</var> がプロミスを含んでいない場合は、<strong>非同期に解決される</strong> {{JSxRef("Promise")}}。</li> - <li>それ以外の場合は<strong>待ち状態の</strong> {{JSxRef("Promise")}}。ここで返されたプロミスは、与えられた反復可能オブジェクト内のいずれかのプロミスが満足したとき、またはすべてのプロミスが拒否されたときに、非同期的に (スタックが空になるとすぐに) 解決または拒否されます。</li> -</ul> - -<h2 id="Description" name="Description">解説</h2> - -<p>このメソッドは、最初に満足するプロミスを返すのに便利です。1つのプロミスが満足した後に短絡するので、1つのプロミスが見つかったら他のプロミスが満足するのを待つことはありません。 {{JSxRef("Promise.all()")}} が満足した値の<em>配列</em>を返すのとは異なり、 (少なくとも1つのプロミスが満足したと仮定すると) 満足した値は 1 つしか得られません。これは、1つのプロミスが満足する必要があるが、どちらのプロミスが満足するかは関係ないときに有益な場合があります。また {{JSxRef("Promise.race()")}} が最初に<em>完了した</em>値 (満足または拒否のいずれか) を返すのとは異なり、このメソッドは最初に<em>満足した</em>値を返します。このメソッドは、最初のプロミスが満足するまでは、すべての拒否されたプロミスを無視します。</p> - -<h3 id="Fulfilment" name="Fulfilment">満足</h3> - -<p>渡されたプロミスのうちのいずれかが満足した場合、返却されるプロミスは他のプロミスが満足または拒否されているかどうかにかかわらず、満足したプロミスの値で非同期に満足します。</p> - -<ul> - <li>空の <var>iterable</var> が渡された場合は、このメソッドはすでに解決済みのプロミスを (同期的に) 返します。</li> - <li>渡されたプロミスのいずれかが満足するか、プロミスがない場合は、 <code>Promise.any</code> で返されるプロミスは非同期で満足します。</li> -</ul> - -<h3 id="Rejection" name="Rejection">拒否</h3> - -<p>渡されたすべてのプロミスが拒否された場合、 <code>Promise.any</code> は {{JSxRef("AggregateError")}} オブジェクトで非同期に拒否され、これは{{JSxRef("Error")}} を継承しており、拒否された値の配列を持つ <code>errors</code> プロパティを含みます。</p> - -<h2 id="Examples" name="Examples">例</h2> - -<h3 id="First_to_fulfil" name="First_to_fulfil">最初に満足するもの</h3> - -<p><code>Promise.any()</code> は、先に拒否されたプロミスがあったとしても、最初に満足したプロミスで解決されます。これは {{jsxref("Promise.race()")}} が最初に決定したプロミスで解決または拒否されるのとは対照的です。</p> - -<pre class="brush: js notranslate">const pErr = new Promise((resolve, reject) => { - reject("Always fails"); -}); - -const pSlow = new Promise((resolve, reject) => { - setTimeout(resolve, 500, "Done eventually"); -}); - -const pFast = new Promise((resolve, reject) => { - setTimeout(resolve, 100, "Done quick"); -}); - -Promise.any([pErr, pSlow, pFast]).then((value) => { - console.log(value); - // pFast fulfils first -}) -// 期待される出力: "Done quick" -</pre> - -<h3 id="Rejections_with_AggregateError" name="Rejections_with_AggregateError">AggregateError での拒否</h3> - -<p><code>Promise.any()</code> は満足したプロミスがないと {{jsxref("AggregateError")}} で拒否されます。</p> - -<pre class="brush: js notranslate">const pErr = new Promise((resolve, reject) => { - reject('Always fails'); -}); - -Promise.any([pErr]).catch((err) => { - console.log(err); -}) -// 期待される出力: "AggregateError: No Promise in Promise.any was resolved" -</pre> - -<h3 id="Displaying_the_first_image_loaded" name="Displaying_the_first_image_loaded">最初に読み込まれた画像の表示</h3> - -<p>この例では、画像を読み込んで blob を返す関数があります。 <code>Promise.any()</code> を使用して二つの画像を読み込み、先に利用可能になった方 (つまり、プロミスが解決された方) を表示します。</p> - -<pre class="brush: js notranslate">function fetchAndDecode(url) { - return fetch(url).then(response => { - if(!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } else { - return response.blob(); - } - }) -} - -let coffee = fetchAndDecode('coffee.jpg'); -let tea = fetchAndDecode('tea.jpg'); - -Promise.any([coffee, tea]).then(value => { - let objectURL = URL.createObjectURL(value); - let image = document.createElement('img'); - image.src = objectURL; - document.body.appendChild(image); -}) -.catch(e => { - console.log(e.message); -});</pre> - -<h2 id="Specifications" name="Specifications">仕様書</h2> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">仕様書</th> - </tr> - </thead> - <tbody> - <tr> - <td>{{SpecName('Promise.any')}}</td> - </tr> - </tbody> -</table> - -<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2> - -<p>{{Compat("javascript.builtins.Promise.any")}}</p> - -<h2 id="See_also" name="See_also">関連情報</h2> - -<ul> - <li>{{JSxRef("Promise")}}</li> - <li>{{JSxRef("Promise.allSettled()")}}</li> - <li>{{JSxRef("Promise.all()")}}</li> - <li>{{JSxRef("Promise.race()")}}</li> -</ul> diff --git a/files/ja/web/javascript/reference/global_objects/promise/any/index.md b/files/ja/web/javascript/reference/global_objects/promise/any/index.md new file mode 100644 index 0000000000..e68101da41 --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/promise/any/index.md @@ -0,0 +1,136 @@ +--- +title: Promise.any() +slug: Web/JavaScript/Reference/Global_Objects/Promise/any +tags: + - JavaScript + - メソッド + - プロミス + - Reference + - Polyfill +browser-compat: javascript.builtins.Promise.any +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/any +--- +{{JSRef}} + +`Promise.any()` は {{JSxRef("Promise")}} オブジェクトの集合の反復可能オブジェクトを受け取り、反復可能オブジェクトの中にあるプロミスの一つが履行されるとすぐに、そのプロミスの値で解決される単一のプロミスを返します。反復可能オブジェクトの中に履行されたプロミスがない場合 (与えられたプロミスがすべて拒否された場合)、返されたプロミスは {{JSxRef("AggregateError")}} という、個々のエラーをグループ化した {{JSxRef("Error")}} の新しいサブクラスで拒否されます。 + +{{EmbedInteractiveExample("pages/js/promise-any.html")}} + +## 構文 + + Promise.any(iterable); + +### 引数 + +- `iterable` + - : [反復可能](/ja/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol)オブジェクト、例えば {{JSxRef("Array")}} です。 + +### 返値 + +- 渡された*反復可能*オブジェクトが空の場合は、**拒否済みの** {{JSxRef("Promise")}} です。 +- 渡された*反復可能*オブジェクトにプロミスがなかった場合は、**非同期に解決**される {{JSxRef("Promise")}} です。 +- それ以外の場合は**待ち状態**の {{JSxRef("Promise")}} です。ここで返されたプロミスは、与えられた反復可能オブジェクト内のいずれかのプロミスが解決されたとき、またはすべてのプロミスが拒否されたとき、**非同期的に** (スタックが空になるとすぐに) 解決または拒否されます。 + +## 解説 + +このメソッドは、最初に履行されたプロミスを返すのに便利です。 1 つのプロミスが履行した後に短絡するので、 1 つのプロミスが見つかったら他のプロミスが履行されるのを待つことはありません。 {{JSxRef("Promise.all()")}} が履行値の*配列*を返すのとは異なり、 (少なくとも 1 つのプロミスが履行したと仮定すると) 履行値は 1 つしか得られません。これは、 1 つのプロミスが履行される必要があるが、どのプロミスが履行されるかは関係ないときに有益な場合があります。なお、もう一つの違いとして、このメソッドは*空の反復可能*オブジェクトを受け取ったときには拒否されます。 + +また、 {{JSxRef("Promise.race()")}} が最初に*決定*された値 (履行されたか拒否されたか) を返すのとは異なり、このメソッドは最初に*履行*された値を返します。このメソッドは、最初にプロミスが履行されるまで、すべての拒否されたプロミスを無視します。 + +### 履行の場合 + +返却されたプロミスは、引数として渡された*反復可能*オブジェクトの中で**最初に**解決された値 (またはプロミスではない値) で解決します。 + +- 空でない*反復可能*オブジェクトが渡され、**いずれか**のプロミスが履行されたか、プロミスではなかった場合、このメソッドから返却されるプロミスは非同期に履行されます。 + +### 拒否の場合 + +渡されたすべてのプロミスが拒否された場合、 `Promise.any` は {{JSxRef("AggregateError")}} オブジェクトで非同期に拒否されます。これはを継承しており、拒否された値の配列を持つ errors` プロパティを含みます。 + +- 空の*反復可能*オブジェクトが渡された場合、このメソッドから返却されたプロミスは同期的に拒否されます。拒否の理由は `AggregateError` オブジェクトであり、その `errors` プロパティは空の配列になります。 + +## 例 + +### 最初に履行されるもの + +`Promise.any()` は、先に拒否されたプロミスがあったとしても、最初に履行されたプロミスで解決されます。これは {{jsxref("Promise.race()")}} が、最初に決定されたプロミスで解決または拒否されるのとは対照的です。 + +```js +const pErr = new Promise((resolve, reject) => { + reject("Always fails"); +}); + +const pSlow = new Promise((resolve, reject) => { + setTimeout(resolve, 500, "Done eventually"); +}); + +const pFast = new Promise((resolve, reject) => { + setTimeout(resolve, 100, "Done quick"); +}); + +Promise.any([pErr, pSlow, pFast]).then((value) => { + console.log(value); + // pFast fulfils first +}) +// 期待される出力: "Done quick" +``` + +### AggregateError での拒否 + +`Promise.any()` は履行されたプロミスがないと {{jsxref("AggregateError")}} で拒否されます。 + +```js +const pErr = new Promise((resolve, reject) => { + reject('Always fails'); +}); + +Promise.any([pErr]).catch((err) => { + console.log(err); +}) +// 期待される出力: "AggregateError: No Promise in Promise.any was resolved" +``` + +### 最初に読み込まれた画像の表示 + +この例では、画像を読み込んで blob を返す関数があります。 `Promise.any()` を使用して二つの画像を読み込み、先に利用可能になった方 (つまり、プロミスが解決された方) を表示します。 + +```js +function fetchAndDecode(url) { + return fetch(url).then(response => { + if(!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } else { + return response.blob(); + } + }) +} + +let coffee = fetchAndDecode('coffee.jpg'); +let tea = fetchAndDecode('tea.jpg'); + +Promise.any([coffee, tea]).then(value => { + let objectURL = URL.createObjectURL(value); + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +}) +.catch(e => { + console.log(e.message); +}); +``` + +## 仕様書 + +{{Specifications}} + +## ブラウザーの互換性 + +{{Compat}} + +## 関連情報 + +- `Promise.any` のポリフィルは [`core-js`](https://github.com/zloirock/core-js#ecmascript-promise) で利用できます +- {{JSxRef("Promise")}} +- {{JSxRef("Promise.allSettled()")}} +- {{JSxRef("Promise.all()")}} +- {{JSxRef("Promise.race()")}} diff --git a/files/ja/web/javascript/reference/global_objects/promise/catch/index.html b/files/ja/web/javascript/reference/global_objects/promise/catch/index.html index 4b2d016a74..277bda3b8a 100644 --- a/files/ja/web/javascript/reference/global_objects/promise/catch/index.html +++ b/files/ja/web/javascript/reference/global_objects/promise/catch/index.html @@ -11,7 +11,7 @@ translation_of: Web/JavaScript/Reference/Global_Objects/Promise/catch --- <div>{{JSRef}}</div> -<p><code><strong>catch()</strong></code> メソッドは <code>Promise</code> を返しますが、拒絶された場合のみ扱います。 {{jsxref("Promise.then", "Promise.prototype.then(undefined, onRejected)")}} の呼び出しと同じ動作をします (実際、 <code>obj.catch(onRejected)</code> の呼び出しは内部的に <code>obj.then(undefined, onRejected)</code> を呼び出しています)。つまり、返値を <code>undefined</code> にフォールバックしたい場合でも、 <code>onRejected</code> 関数を提供する必要があります。 - 例えば、 <code>obj.catch(() => {})</code> のようにします。</p> +<p><code><strong>catch()</strong></code> メソッドは <code>Promise</code> を返しますが、拒否された場合のみ扱います。 {{jsxref("Promise.then", "Promise.prototype.then(undefined, onRejected)")}} の呼び出しと同じ動作をします (実際、 <code>obj.catch(onRejected)</code> の呼び出しは内部的に <code>obj.then(undefined, onRejected)</code> を呼び出しています)。つまり、返値を <code>undefined</code> にフォールバックしたい場合でも、 <code>onRejected</code> 関数を提供する必要があります。 - 例えば、 <code>obj.catch(() => {})</code> のようにします。</p> <div>{{EmbedInteractiveExample("pages/js/promise-catch.html")}}</div> @@ -33,9 +33,9 @@ p.catch(function(<var>reason</var>) { <dd><code>Promise</code> が失敗した時に呼び出される {{jsxref("Function")}} です。この関数は一つの引数を持ちます。 <dl> <dt><code><var>reason</var></code></dt> - <dd>拒絶された理由です。</dd> + <dd>拒否された理由です。</dd> </dl> - <code>catch()</code> で返される Promise は、 <code><var>onRejected</var></code> がエラーを発生させた場合、または返される Promise それ自体が拒絶された場合は、拒絶となります。それ以外の場合は、解決となります。</dd> + <code>catch()</code> で返される Promise は、 <code><var>onRejected</var></code> がエラーを発生させた場合、または返される Promise それ自体が拒否された場合は、拒否となります。それ以外の場合は、解決となります。</dd> </dl> <h3 id="Return_value" name="Return_value">返値</h3> diff --git a/files/ja/web/javascript/reference/global_objects/promise/index.html b/files/ja/web/javascript/reference/global_objects/promise/index.html deleted file mode 100644 index 3b1d149baa..0000000000 --- a/files/ja/web/javascript/reference/global_objects/promise/index.html +++ /dev/null @@ -1,365 +0,0 @@ ---- -title: Promise -slug: Web/JavaScript/Reference/Global_Objects/Promise -tags: - - Class - - ECMAScript 2015 - - JavaScript - - Promise - - Reference - - クラス - - プロミス -translation_of: Web/JavaScript/Reference/Global_Objects/Promise ---- -<div>{{JSRef}}</div> - -<p><strong><code>Promise</code></strong> オブジェクトは非同期処理の最終的な完了処理 (もしくは失敗) およびその結果の値を表現します。</p> - -<p>プロミスの挙動と使用法について学ぶには、最初に <a href="/ja/docs/Web/JavaScript/Guide/Using_promises">Promise の使用</a>をお読みください。</p> - -<h2 id="Description" name="Description">解説</h2> - -<p><code><strong>Promise</strong></code> インターフェイスは作成時点では分からなくてもよい値へのプロキシです。 Promise を用いることで、非同期アクションの成功や失敗に対するハンドラーを関連付けることができます。これにより、非同期メソッドは、最終的な値を返すのではなく、未来のある時点で値を持つ Promise を返すことで、同期メソッドと同じように値を返すことができるようになります。</p> - -<p><code>Promise</code> の状態は以下のいずれかとなります。</p> - -<ul> - <li><ruby>待機<rp> (</rp><rt><em>pending</em></rt></ruby>: 初期状態。成功も失敗もしていません。</li> - <li><ruby>満足<rp> (</rp><rt><em>fulfilled</em></rt><rp>)</rp></ruby>: 処理が成功して完了したことを意味します。</li> - <li><ruby>拒絶<rp> (</rp><rt><em>rejected</em></rt><rp>)</rp></ruby>: 処理が失敗したことを意味します。</li> -</ul> - -<p>待機状態のプロミスは、何らかの値を持つ満足 (<em>fulfilled</em>) 状態、もしくは何らかの理由 (エラー) を持つ拒絶 (<em>rejected</em>) 状態のいずれかに変わります。そのどちらとなっても、<code>then</code> メソッドによって関連付けられたハンドラーが呼び出されます。 (対応するハンドラーが割り当てられたとき、既にプロミスが成功または失敗していても、そのハンドラーは呼ばれます。よって、非同期処理とその関連付けられたハンドラーとの競合は発生しません。)</p> - -<p><code>{{JSxRef("Promise.then", "Promise.prototype.then()")}}</code> メソッドと <code>{{JSxRef("Promise.catch", "Promise.prototype.catch()")}}</code> メソッドもまた Promise を返すので、これらをチェーン (連鎖) させることができます。</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/15911/promises.png" style="height: 297px; width: 801px;"></p> - -<div class="blockIndicator note"> -<p><strong>混乱を避けるために:</strong> Scheme に代表されるいくつかの言語では、遅延評価や計算を延期する機構を持っており、これらも "Promise" と呼ばれます。 JavaScript における Promise は、すでに起きつつある処理を表します。そしてこの処理はコールバックを使うことでチェーンさせることができます。式を遅延評価する方法を探しているのであれば、引数なしの<a href="/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions">アロー関数</a>を考えてください。 <code>f = () => <em>expression</em></code> のように実現でき、遅延評価される式が作成され、 <code>f()</code> を呼ぶことでその式を評価できます。</p> -</div> - -<div class="blockIndicator note"> -<p><strong>注</strong>: Promise は fulfilled か failed のどちらかになった場合は、 pending ではなく settled と呼ばれます。また解決 (<em>resolved</em>) という用語も目にされたことがあると思います。解決とは、Promise が解決または他の promise の状態にマッチするために" locked in "したことを意味します。<a href="https://github.com/domenic/promises-unwrapping/blob/master/docs/states-and-fates.md">States and fates</a> では、 Promise の技術についてより詳細に述べられています。</p> -</div> - -<h3 id="Chained_Promises" name="Chained_Promises">連鎖したプロミス</h3> - -<p><code>promise.then()</code>, <code>promise.catch()</code>, <code>promise.finally()</code> の各メソッドは、決定したプロミスにさらなるアクションを関連付けるために使用されます。これらのメソッドはまた、新しく生成されたプロミスオブジェクトを返します。例えば、このようになります。</p> - -<dl> - <dd> - <pre class="brush: js notranslate">const myPromise = - (new Promise(myExecutorFunc)) - .then(handleFulfilledA,handleRejectedA) - .then(handleFulfilledB,handleRejectedB) - .then(handleFulfilledC,handleRejectedC); - -// または、おそらく次の方がよい ... - -const myPromise = - (new Promise(myExecutorFunc)) - .then(handleFulfilledA) - .then(handleFulfilledB) - .then(handleFulfilledC) - .catch(handleRejectedAny);</pre> - </dd> -</dl> - -<p>拒絶されたプロミスの処理が早すぎると、プロミスの連鎖のさらに下の方に影響を及ぼします。エラーはすぐに処理しなければならないので、選択の余地がないこともあります。 (結果を処理するためのテクニックについては、下記の例の <code>throw -999</code> を参照してください。) 一方で、すぐに必要がない場合は、最後の .catch() 文までエラー処理をしない方がシンプルです。</p> - -<p>これら2つの関数のシグネチャはシンプルで、任意の型の引数を1つだけ受け取ることができます。これらの関数を書くのはプログラマーです。これらの関数の終了条件は、チェーン内の次のプロミスの「解決」状態を決定します。 <code>throw</code> 以外の終了条件は "解決" の状態を生み出し、一方、 <code>throw</code> で終了すると "拒否" の状態を生み出します。</p> - -<pre class="brush: js notranslate">handleFulfilled(value) { /*...*/; return nextValue; } -handleRejection(reason) { /*...*/; throw nextReason; } -handleRejection(reason) { /*...*/; return nextValue; }</pre> - -<p>返される <code>nextValue</code> は、別のプロミスオブジェクトにすることもでき、この場合はプロミスは動的にチェーンに挿入されます。</p> - -<p><code>.then()</code> が適切な関数欠いている場合、処理は単純にチェーンの次のリンクへと続きます。したがってチェーンは、すべての <code>handleRejection</code> を最後の <code>.catch()</code> まで、安全に省略することができます。 同様に、<code>.catch()</code> は、実際には <code>handleFulfilled</code> 用のスロットのないただの <code>.then()</code> です。</p> - -<p>プロミスのチェーンはロシアの人形のように入れ子にすることができますが、スタックの最上位のように取り出します。チェーンの最初のプロミスは最も深いところに入れ子になり、最初に取り出されます。</p> - -<pre class="notranslate">(promise D, (promise C, (promise B, (promise A) ) ) )</pre> - -<p><code>nextValue</code> がプロミスである場合、その効果は動的な置換です。 <code>return</code> によってプロミスが取り出されますが、 <code>nextValue</code> のプロミスはその場所に押し込まれます。上に示した入れ子では、"promise B" に関連付けられた <code>.then()</code> が "promise X" の <code>nextValue</code> を返すとします。 結果としての入れ子は以下のようになります。</p> - -<pre class="notranslate">(promise D, (promise C, (promise X) ) )</pre> - -<p>プロミスは複数の入れ子に参加することができます。以下のコードでは、 <code>promiseA</code> が「確定」状態に移行すると、 <code>.then()</code> の両方のインスタンスが呼び出されます。</p> - -<pre class="brush: js notranslate">const promiseA = new Promise(myExecutorFunc); -const promiseB = promiseA.then(handleFulfilled1, handleRejected1); -const promiseC = promiseA.then(handleFulfilled2, handleRejected2); -</pre> - -<p>既に「解決済み」のプロミスにアクションを割り当てることができます。その場合、アクションは (適切であれば) 最初の非同期の機会に実行されます。プロミスは非同期であることが保証されていることに注意してください。したがって、既に「解決済み」のプロミスに対するアクションは、スタックがクリアされ、クロックティックが経過した後にのみ実行されます。この効果は <code>setTimeout(action,10)</code> とよく似ています</p> - -<pre class="brush: js notranslate">const promiseA = new Promise( (resolutionFunc,rejectionFunc) => { - resolutionFunc(777); -}); -// この時点で、 "promiseA" はすでに解決されています。 -promiseA.then( (val) => console.log("asynchronous logging has val:",val) ); -console.log("immediate logging"); - -// 以下の順序で出力が行われます。 -// immediate logging -// asynchronous logging has val: 777 -</pre> - -<h2 id="Constructor" name="Constructor">コンストラクター</h2> - -<dl> - <dt>{{jsxref("Promise/Promise", "Promise()")}}</dt> - <dd>新しい <code>Promise</code> オブジェクトを生成します。このコンストラクターは主にまだプロミスに対応していない関数をラップするために使われます。</dd> -</dl> - -<h2 id="Static_methods" name="Static_methods">静的メソッド</h2> - -<dl> - <dt>{{JSxRef("Promise.all", "Promise.all(iterable)")}}</dt> - <dd>すべてのプロミスが解決されるか、拒否されるかするまで待ちます。</dd> - <dd>返却されたプロミスが解決された場合、解決されたプロミスが、複数のプロミスが含まれる iterable で定義された通りの順番で入った集合配列の値によって解決されます。</dd> - <dd>拒否された場合は、 iterable の中で拒否された最初のプロミスの理由によって拒否されます。</dd> - <dt>{{JSxRef("Promise.allSettled", "Promise.allSettled(iterable)")}}</dt> - <dd>すべての Promise が完了する (それぞれが解決するか、拒否される) まで待ちます。</dd> - <dd>Promise を返し、これはすべての与えられた Promise が解決または拒否された後で、それぞれの Promise の結果を記述するオブジェクトの配列で解決されます。</dd> - <dt>{{JSxRef("Promise.any", "Promise.any(iterable)")}}</dt> - <dd>Promise オブジェクトの反復可能オブジェクトを取り、反復可能オブジェクトの中のプロミスのうちの一つが満足され次第、そのプロミスから受け取った値で解決する単一のプロミスを返します。</dd> - <dt>{{JSxRef("Promise.race", "Promise.race(iterable)")}}</dt> - <dd>Promise のうちの1つが解決または拒否されるまで待ちます。</dd> - <dd>返された Promise が解決された場合、 iterable の中で最初に解決された Promise の値によって解決されます。</dd> - <dd>拒否された場合、最初に拒否された Promise の理由によって拒否されます。</dd> - <dt>{{JSxRef("Promise.reject", "Promise.reject(reason)")}}</dt> - <dd>与えられた理由で拒否された新しい <code>Promise</code> オブジェクトを返します。</dd> - <dt>{{JSxRef("Promise.resolve", "Promise.resolve(value)")}}</dt> - <dd>与えられた値で解決された新しい <code>Promise</code> オブジェクトを返します。もし値が thenable (つまり <code>then</code> メソッドを持っているオブジェクト) ならば、返される Promise はその thenable をたどり、その結果を採用します。そうでなければ、返される Promise は与えられた値で解決されます。</dd> - <dd>一般に、ある値がプロミスかどうかがわからない場合は、{{JSxRef("Promise.resolve", "Promise.resolve(value)")}} を使って Promise にして扱います。</dd> -</dl> - -<h2 id="Instance_methods" name="Instance_methods">インスタンスメソッド</h2> - -<dl> - <dt>{{jsxref("Promise.prototype.catch()")}}</dt> - <dd>プロミスに失敗ハンドラーコールバックを付加します。呼ばれるとコールバックの返値、または、オリジナルのプロミスが成功しているなら、その成功値によって完了している新しいプロミスを返します。</dd> - <dt>{{jsxref("Promise.prototype.then()")}}</dt> - <dd>プロミスに成功ハンドラーと失敗ハンドラーを付加します。呼ばれたハンドラーの戻り値によって解決している新しいプロミスを返します。または、プロミスが扱われなかった場合 (つまり <code>onFulfilled</code> や <code>onRejected</code> が関数でない場合) には、元の完了した値に解決しているプロミスを返します。</dd> - <dt>{{jsxref("Promise.prototype.finally()")}}</dt> - <dd>プロミスにハンドラーを付加し、元のプロミスが解決されたときに解決される新しいプロミスを返します。このハンドラーは、成功か失敗かに関わらず、元のプロミスが完了したときに呼ばれます。</dd> -</dl> - -<h2 id="Examples" name="Examples">例</h2> - -<h3 id="Basic_Example" name="Basic_Example">基本的な使用例</h3> - -<pre class="brush: js; notranslate">let myFirstPromise = new Promise((resolve, reject) => { - // We call resolve(...) when what we were doing asynchronously was successful, and reject(...) when it failed. - // In this example, we use setTimeout(...) to simulate async code. - // In reality, you will probably be using something like XHR or an HTML5 API. - setTimeout( function() { - resolve("Success!") // Yay! Everything went well! - }, 250) -}) - -myFirstPromise.then((successMessage) => { - // successMessage is whatever we passed in the resolve(...) function above. - // It doesn't have to be a string, but if it is only a succeed message, it probably will be. - console.log("Yay! " + successMessage) -}); - -</pre> - -<h3 id="Example_with_diverse_situations" name="Example_with_diverse_situations">多様な状況に対応した例</h3> - -<p>この例では、プロミス機能を使用するための多様なテクニックと、発生する可能性のある多様な状況を示しています。これを理解するには、まずコードブロックの一番下までスクロールして、プロミスの連鎖を調べてください。最初のプロミスが提供されると、プロミスの連鎖が続きます。このチェーンは <code>.then()</code> の呼び出しで構成され、通常は (必ずしもそうとは限りませんが) 最後に単一の <code>.catch()</code> があり、オプションで <code>.finally()</code> が続きます。この例では、プロミスチェーンはカスタムで書かれた <code>new Promise()</code> コンストラクターによって開始されますが、実際には、プロミスチェーンは通常、プロミスを返す API 関数 (他の誰かが書いたもの) から開始されます。</p> - -<p>関数 <code>tetheredGetNumber()</code> の例では、非同期呼び出しを設定している間、またはコールバック内で、またはその両方で <code>reject()</code> を使用してプロミスを生成することを示しています。 関数 <code>promiseGetWord()</code> は、API 関数がどのように自己完結型の方法でプロミスを生成して返すかを示しています。</p> - -<p>関数 <code>troubleWithGetNumber()</code> は <code>throw()</code> で終わることに注意してください。これは、 ES6 のプロミスチェーンでは、エラーが発生した後で、 "throw()" がなく、エラーが "fixed" であるようにみえても、すべての <code>.then()</code> のプロミスを通過するため、強制的に行われています。これは面倒なので、 <code>.then()</code> プロミスのチェーン全体で <code>rejectionFunc</code> を省略して、最終的な <code>catch()</code> で単一の <code>rejectionFunc</code> を使用するのが一般的です。 別の方法としては、特別な値を投げるという方法があります (この場合は"-999" ですが、カスタムのエラー種別の方が適切です)。</p> - -<p>このコードは NodeJS で実行できます。実際にエラーが発生しているのを見ることで理解度が高まります。より多くのエラーを強制的に発生させるには、 <code>threshold</code> の値を変更します。</p> - -<pre class="brush: js notranslate">"use strict"; - -// To experiment with error handling, "threshold" values cause errors randomly -const THRESHOLD_A = 8; // can use zero 0 to guarantee error - -function tetheredGetNumber(resolve, reject) { - try { - setTimeout( - function() { - const randomInt = Date.now(); - const value = randomInt % 10; - try { - if(value >= THRESHOLD_A) { - throw new Error(`Too large: ${value}`); - } - } catch(msg) { - reject(`Error in callback ${msg}`); - } - resolve(value); - return; - }, 500); - // To experiment with error at set-up, uncomment the following 'throw'. - // throw new Error("Bad setup"); - } catch(err) { - reject(`Error during setup: ${err}`); - } - return; -} - -function determineParity(value) { - const isOdd = value % 2 ? true : false ; - const parityInfo = { theNumber: value, isOdd: isOdd }; - return parityInfo; -} - -function troubleWithGetNumber(reason) { - console.error(`Trouble getting number: ${reason}`); - throw -999; // must "throw" something, to maintain error state down the chain -} - -function promiseGetWord(parityInfo) { - // The "tetheredGetWord()" function gets "parityInfo" as closure variable. - var tetheredGetWord = function(resolve,reject) { - const theNumber = parityInfo.theNumber; - const threshold_B = THRESHOLD_A - 1; - if(theNumber >= threshold_B) { - reject(`Still too large: ${theNumber}`); - } else { - parityInfo.wordEvenOdd = parityInfo.isOdd ? 'odd' : 'even'; - resolve(parityInfo); - } - return; - } - return new Promise(tetheredGetWord); -} - -(new Promise(tetheredGetNumber)) - .then(determineParity,troubleWithGetNumber) - .then(promiseGetWord) - .then((info) => { - console.log("Got: ",info.theNumber," , ", info.wordEvenOdd); - return info; - }) - .catch((reason) => { - if(reason === -999) { - console.error("Had previously handled error"); - } - else { - console.error(`Trouble with promiseGetWord(): ${reason}`); - } - }) - .finally((info) => console.log("All done")); - -</pre> - -<h3 id="Advanced_Example" name="Advanced_Example">応用例</h3> - -<div class="hidden"> -<pre class="brush: html notranslate"><button id="btn">Make a promise!</button> -<div id="log"></div> -</pre> -</div> - -<p>以下の例は <code>Promise</code> の仕組みを示したものです。 <code>testPromise()</code> メソッドは {{HTMLElement("button")}} をクリックする度に呼び出されます。<code>testPromise()</code> メソッドは、 {{domxref("window.setTimeout()")}} を用いて、1秒から 3秒のランダムな時間の後、メソッドがこれまでに呼ばれた回数で成功する Promise を作成します。 <code>Promise()</code> コンストラクターは Promise を作成するために使用されます。</p> - -<p>プロミスが満足したことは、 {{JSxRef("Promise.prototype.then()","p1.then()")}} で設定されたコールバックによって記録されます。この記録から、メソッドの同期処理部分が、 Promise による非同期処理からどのように分離されているかがわかります。</p> - -<pre class="brush: js; notranslate">'use strict'; -var promiseCount = 0; - -function testPromise() { - let thisPromiseCount = ++promiseCount; - - let log = document.getElementById('log'); - log.insertAdjacentHTML('beforeend', thisPromiseCount + - ') 開始 (<small>同期処理開始</small>)<br/>'); - - // 新しい Promise を作成: 1~3秒後に結果を返すことを約束します - let p1 = new Promise( - // executor 関数は Promise の成功または失敗に応じて呼ばれます - // - (resolve, reject) => { - log.insertAdjacentHTML('beforeend', thisPromiseCount + - ') Promise 開始 (<small>非同期処理開始</small>)<br/>'); - // 非同期を作成するための一例です - window.setTimeout( - function() { - // 約束を果たしました! - resolve(thisPromiseCount); - }, Math.random() * 2000 + 1000); - } - ); - - // Promise が成功した時に何をするかを定めます then() で成功した時 - // catch() で失敗した時 - p1.then( - // メッセージと値を記録します - function(val) { - log.insertAdjacentHTML('beforeend', val + - ') Promise 成功 (<small>非同期処理終了</small>)<br/>'); - }).catch( - // 失敗した理由を記録します - (reason) => { - console.log('Handle rejected promise ('+reason+') here.'); - }); - - log.insertAdjacentHTML('beforeend', thisPromiseCount + - ') Promise は作成されました (<small>同期処理終了</small>)<br/>'); -}</pre> - -<div class="hidden"> -<pre class="brush: js; notranslate">if ("Promise" in window) { - let btn = document.getElementById("btn"); - btn.addEventListener("click",testPromise); -} else { - log = document.getElementById('log'); - log.innerHTML = "Live example not available as your browser doesn't support the <code>Promise<code> interface."; -} -</pre> -</div> - -<p>この例はボタンをクリックすると実行されます。 (ブラウザーが <code>Promise</code> に対応している必要があります。)</p> - -<p>短い時間の間に何度かボタンをクリックすると、それぞれの promise が次々と成功するのがわかります。</p> - -<p>{{EmbedLiveSample("Advanced_Example", "500", "200")}}</p> - -<h3 id="Loading_an_image_with_XHR" name="Loading_an_image_with_XHR">XHR による画像の読み込み</h3> - -<p><code>Promise</code> と {{domxref("XMLHttpRequest")}} で画像を読み込む別の例は、 MDN GitHub <a href="https://github.com/mdn/js-examples/tree/master/promises-test">js-examples</a> リポジトリにあり、<a href="https://mdn.github.io/js-examples/promises-test/">動作を確認する</a>ことができます。それぞれの行のコメントで Promise と XHR の構造がよくわかるはずです。</p> - -<h2 id="Specifications" name="Specifications">仕様書</h2> - -<table class="standard-table"> - <tbody> - <tr> - <th scope="col">仕様書</th> - </tr> - <tr> - <td>{{SpecName('ESDraft', '#sec-promise-objects', 'Promise')}}</td> - </tr> - </tbody> -</table> - -<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2> - -<p>{{Compat("javascript.builtins.Promise")}}</p> - -<h2 id="See_also" name="See_also">関連情報</h2> - -<ul> - <li><a href="/ja/docs/Web/JavaScript/Guide/Using_promises">プロミスの使用</a></li> - <li><a href="http://promisesaplus.com/">Promises/A+ specification</a></li> - <li><a href="https://medium.com/@ramsunvtech/promises-of-promise-part-1-53f769245a53">Venkatraman.R - JS Promise (Part 1, Basics)</a></li> - <li><a href="https://medium.com/@ramsunvtech/js-promise-part-2-q-js-when-js-and-rsvp-js-af596232525c#.dzlqh6ski">Venkatraman.R - JS Promise (Part 2 - Using Q.js, When.js and RSVP.js)</a></li> - <li><a href="https://tech.io/playgrounds/11107/tools-for-promises-unittesting/introduction">Venkatraman.R - Tools for Promises Unit Testing</a></li> - <li><a href="http://www.html5rocks.com/en/tutorials/es6/promises/">Jake Archibald: JavaScript Promises: There and Back Again</a></li> - <li><a href="http://de.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript">Domenic Denicola: Callbacks, Promises, and Coroutines – Asynchronous Programming Patterns in JavaScript</a></li> - <li><a href="http://www.mattgreer.org/articles/promises-in-wicked-detail/">Matt Greer: JavaScript Promises ... In Wicked Detail</a></li> - <li><a href="https://www.promisejs.org/">Forbes Lindesay: promisejs.org</a></li> - <li><a href="https://github.com/anonyco/SPromiseMeSpeedJS/blob/master/README.md">Speed-polyfill to polyfill both promise availability and promise performance.</a></li> - <li><a href="https://github.com/jakearchibald/es6-promise/">Promise polyfill</a></li> - <li><a href="https://www.udacity.com/course/javascript-promises--ud898">Udacity: JavaScript Promises</a></li> -</ul> diff --git a/files/ja/web/javascript/reference/global_objects/promise/index.md b/files/ja/web/javascript/reference/global_objects/promise/index.md new file mode 100644 index 0000000000..821495840f --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/promise/index.md @@ -0,0 +1,435 @@ +--- +title: Promise +slug: Web/JavaScript/Reference/Global_Objects/Promise +tags: + - クラス + - ECMAScript 2015 + - JavaScript + - Promise + - Reference + - promise.all + - Polyfill +browser-compat: javascript.builtins.Promise +translation_of: Web/JavaScript/Reference/Global_Objects/Promise +--- +{{JSRef}} + +**`Promise`** オブジェクトは、非同期処理の完了 (もしくは失敗) の結果およびその結果の値を表します。 + +{{AvailableInWorkers}} + +プロミスの挙動と使用法について学ぶには、最初に[プロミスの使用](/ja/docs/Web/JavaScript/Guide/Using_promises)をお読みください。 + +## 解説 + +プロミス (**`Promise`**) は、作成された時点では分からなくてもよい値へのプロキシーです。非同期のアクションの成功値または失敗理由にハンドラーを結びつけることができます。これにより、非同期メソッドは結果の値を返す代わりに、未来のある時点で値を提供する*プロミス*を返すことで、同期メソッドと同じように値を返すことができるようになります。 + +`Promise` の状態は以下のいずれかとなります。 + +- 待機 (_pending_): 初期状態。成功も失敗もしていません。 +- 履行 (_fulfilled_): 処理が成功して完了したことを意味します。 +- 拒否 (_rejected_): 処理が失敗したことを意味します。 + +待機状態のプロミスは、何らかの値を持つ履行 (_fulfilled_) 状態、もしくは何らかの理由 (エラー) を持つ拒否 (_rejected_) 状態のいずれかに変わります。そのどちらとなっても、`then` メソッドによって関連付けられたハンドラーが呼び出されます。対応するハンドラーが割り当てられたとき、既にプロミスが履行または拒否状態になっていても、そのハンドラーは呼び出されます。よって、非同期処理とその関連付けられたハンドラーとの競合は発生しません。 + +`{{JSxRef("Promise.then", "Promise.prototype.then()")}}` メソッドと `{{JSxRef("Promise.catch", "Promise.prototype.catch()")}}` メソッドもまたプロミスを返すので、これらを連鎖 (chain) させることができます。 + +![](promises.png) + +> **Note:** Scheme に代表される一部の言語では、遅延評価や計算を延期する機構を持っており、これらも「プロミス」と呼ばれます。 JavaScript におけるプロミスは、すでに起きつつある処理を表し、この処理はコールバックを使うことで連鎖させることができます。式を遅延評価する方法を探しているのであれば、引数なしの<a href="/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions">アロー関数</a>を検討してください。 `f = () => expression` で遅延評価される式が作成でき、 `f()` を実行することで評価を実行することができます。 + +> **Note:** プロミスは履行状態または拒否状態になった場合は、待機ではなく決定 (_settled_) と呼ばれます。また解決 (_resolved_) という用語も見かけるでしょう。これはプロミスが決定したか、他のプロミスの状態に一致させるために「ロックイン」したことを表します。 [States and fates](https://github.com/domenic/promises-unwrapping/blob/master/docs/states-and-fates.md) には、プロミスの用語についての詳細説明があります。 + +### 複数のプロミスの連鎖 + +`promise.then()`, `promise.catch()`, `promise.finally()` の各メソッドは、決定したプロミスにさらなるアクションを結びつけるために使用します。 + +`.then()` メソッドは、最大で 2 つの引数を取ります。1 番目の引数は、プロミスが解決した場合のコールバック関数で、 2 番目の引数は、拒否された場合のコールバック関数です。それぞれの `.then()` は新たに生成されたプロミスオブジェクトを返します。このオブジェクトは、オプションで連鎖に使用することができます。例えば、このようになります。 + +```js +const myPromise = new Promise((resolve, reject) => { + setTimeout(() => { + resolve('foo'); + }, 300); +}); + +myPromise + .then(handleResolvedA, handleRejectedA) + .then(handleResolvedB, handleRejectedB) + .then(handleResolvedC, handleRejectedC); +``` + +`.then()` に Promise オブジェクトを返すコールバック関数がない場合でも、連鎖の次のリンクへと処理が進みます。したがって、連鎖では最後の `.catch()` まで、すべての*拒否*のコールバック関数を省略しても安全です。 + +それぞれの `.then()` で拒否されたプロミスを扱うと、プロミスの連鎖のさらに先に影響を及ぼします。エラーを直ちに処理しなければならないため、選択の余地がない場合もあります。このような場合には、連鎖的にエラー状態を維持するために、何らかの種類のエラーを発生させる必要があります。一方で、緊急の必要性がない場合は、最後の `.catch()` ステートメントまでエラー処理を行わない方がシンプルです。 `.catch()` は、実際には、単なる `.then()` からプロミスが解決されたときのためのコールバック関数のスロットを抜いたものです。 + +```js +myPromise +.then(handleResolvedA) +.then(handleResolvedB) +.then(handleResolvedC) +.catch(handleRejectedAny); +``` + +{{JSxRef("Functions/Arrow_functions", "アロー関数式", "", 1)}}をコールバック関数に使用すると、プロミス連鎖の実装は次のようになるでしょう。 + +```js +promise1 +.then(value => { return value + ' and bar'; }) +.then(value => { return value + ' and bar again'; }) +.then(value => { return value + ' and again'; }) +.then(value => { return value + ' and again'; }) +.then(value => { console.log(value) }) +.catch(err => { console.log(err) }); +``` + +プロミスの終了条件は、その連鎖内の次のプロミスの「決定」状態を決定します。解決」状態はプロミスの完了が成功したことを示し、「拒否」状態は成功しなかったことを示します。連鎖内で解決されたそれぞれのプロミスの返値は、次の `.then()` に渡され、拒否された理由は連鎖内の次の拒否ハンドラー関数に渡されます。 + +連鎖のプロミスは、ロシア人形のように入れ子になっていますが、スタックの一番上のように取り出されます。連鎖の最初のプロミスは最も深くネストされており、最初に取り出されます。 + +```plain +(promise D, (promise C, (promise B, (promise A) ) ) ) +``` + +`nextValue` がプロミスである場合、その効果は動的な置換です。 `return` によってプロミスが取り出されますが、 `nextValue` のプロミスはその場所に押し込まれます。上に示した入れ子では、"promise B" に関連付けられた `.then()` が "promise X" の `nextValue` を返すとします。 結果としての入れ子は以下のようになります。 + +```plain +(promise D, (promise C, (promise X) ) ) +``` + +プロミスは複数の入れ子に参加することができます。以下のコードでは、 `promiseA` が「決定」状態に移行すると、 `.then()` の両方のインスタンスが呼び出されます。 + +```js +const promiseA = new Promise(myExecutorFunc); +const promiseB = promiseA.then(handleFulfilled1, handleRejected1); +const promiseC = promiseA.then(handleFulfilled2, handleRejected2); +``` + +既に「決定」状態のプロミスにアクションを割り当てることができます。その場合、アクションは (適切であれば) 最初の非同期の機会に実行されます。プロミスは非同期であることが保証されていることに注意してください。したがって、既に「解決」状態のプロミスに対するアクションは、スタックがクリアされ、クロックティックが経過した後にのみ実行されます。この効果は `setTimeout(action,10)` とよく似ています + +```js +const promiseA = new Promise( (resolutionFunc,rejectionFunc) => { + resolutionFunc(777); +}); +// この時点で、 "promiseA" はすでに解決されています。 +promiseA.then( (val) => console.log("asynchronous logging has val:",val) ); +console.log("immediate logging"); + +// 以下の順序で出力が行われます。 +// immediate logging +// asynchronous logging has val: 777 +``` + +### 現行の設定オブジェクトの追跡 + +設定オブジェクト (settings object) とは、 JavaScript コードの実行時に追加情報を提供する[環境](https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object)のことです。これには、領域やモジュールマップのほか、オリジンなどの HTML 固有の情報も含まれます。現行の設定オブジェクトが追跡されるのは、特定のユーザーコードに対してどの設定オブジェクトを使用すべきかをブラウザーが確実に把握するためです。 + +これをより良く理解するために、領域がどのように問題になるかを詳しく見てみましょう。領域 (**realm**) とは、大まかに言うとグローバルオブジェクトのことです。領域の特徴は、JavaScript のコードを実行するために必要な情報をすべて保持していることです。これには [`Array`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Array) や [`Error`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Error) などのオブジェクトが含まれます。それぞれの設定オブジェクトはこれらの「コピー」を持っており、共有されていません。そのため、プロミスとの関係で予期しない動作をすることがあります。これを回避するために、**現行の設定オブジェクト** (incumbent settings object) と呼ばれるものを追跡します。これは、ある関数呼び出しを担当するユーザーコードのコンテキストに固有の情報を表します。 + +これをもう少し詳しく説明するために、文書に埋め込まれた [`<iframe>`](/ja/docs/Web/HTML/Element/iframe) がホストとどのように通信するかを見てみましょう。すべての Web API は現行の設定オブジェクトを認識しているため、以下のようにすればすべてのブラウザーで動作します。 + +```html +<!DOCTYPE html> +<iframe></iframe> <!-- we have a realm here --> +<script> // we have a realm here as well + const bound = frames[0].postMessage.bind( + frames[0], "some data", "*"); + // bound is a built-in function -- there is no user + // code on the stack, so which realm do we use? + window.setTimeout(bound); + // this still works, because we use the youngest + // realm (the incumbent) on the stack +</script> +``` + +同じ概念をプロミスに適用します。上の例を少し変えてみると、こうなります。 + +```html +<!DOCTYPE html> +<iframe></iframe> <!-- we have a realm here --> +<script> // we have a realm here as well + const bound = frames[0].postMessage.bind( + frames[0], "some data", "*"); + // bound is a built in function -- there is no user + // code on the stack -- which realm do we use? + Promise.resolve(undefined).then(bound); + // this still works, because we use the youngest + // realm (the incumbent) on the stack +</script> +``` + +これを変更して、文書内の `<iframe>` が post メッセージを待ち受けするようにすると、現行の設定オブジェクトの効果を観察することができます。 + +```html +<!-- y.html --> +<!DOCTYPE html> +<iframe src="x.html"></iframe> +<script> + const bound = frames[0].postMessage.bind(frames[0], "some data", "*"); + Promise.resolve(undefined).then(bound); +</script> +``` + +```html +<!-- x.html --> +<!DOCTYPE html> +<script> +window.addEventListener("message", (event) => { + document.querySelector("#text").textContent = "hello"; + // this code will only run in browsers that track the incumbent settings object + console.log(event); +}, false); +</script> +``` + +上記の例では、現行の設定オブジェクトが追跡されたときのみ `<iframe>` の内部のテキストが更新されます。これは、現職のものを追跡しないと、メッセージを送る環境を間違えてしまう可能性があるからです。 + +> **Note:** 現在のところ、現役の領域の追跡は Firefox では完全に実装されており、 Chrome と Safari では部分的に実装されています。 + +## コンストラクター + +- {{jsxref("Promise/Promise", "Promise()")}} + - : 新しい `Promise` オブジェクトを生成します。このコンストラクターは主に、まだプロミスに対応していない関数をラップするために使われます。 + +## 静的メソッド + +- {{JSxRef("Promise.all", "Promise.all(iterable)")}} + + - : すべてのプロミスが解決されるか、拒否されるかするまで待ちます。 + + 返却されたプロミスが解決された場合、解決されたプロミスが、複数のプロミスが含まれる反復可能オブジェクトで定義された順番で入った集合配列の値によって解決されます。 + + 拒否された場合は、反復可能オブジェクトの中で拒否された最初のプロミスの理由によって拒否されます。 + +- {{JSxRef("Promise.allSettled", "Promise.allSettled(iterable)")}} + + - : すべてのプロミスが完了する (それぞれが解決されるか、拒否される) まで待ちます。 + + これはすべての与えられたプロミスが解決または拒否された後で、それぞれのプロミスの結果を記述したオブジェクトの配列で解決される Promise を返します。 + +- {{JSxRef("Promise.any", "Promise.any(iterable)")}} + - : Promise オブジェクトの反復可能オブジェクトを取り、反復可能オブジェクトの中のプロミスのうちの一つが履行され次第、そのプロミスから受け取った値で解決する単一のプロミスを返します。 +- {{JSxRef("Promise.race", "Promise.race(iterable)")}} + + - : プロミスのうちの 1 つが解決または拒否されるまで待ちます。 + + 返されたプロミスが解決された場合、反復可能オブジェクトの中で最初に解決されたプロミスの値によって解決されます。 + + 拒否された場合、最初に拒否されたプロミスの理由によって拒否されます。 + +- {{JSxRef("Promise.reject", "Promise.reject(reason)")}} + - : 与えられた理由で拒否された新しい `Promise` オブジェクトを返します。 +- {{JSxRef("Promise.resolve", "Promise.resolve(value)")}} + + - : 与えられた値で解決された新しい `Promise` オブジェクトを返します。もし値が thenable (つまり `then` メソッドを持っているオブジェクト) ならば、返されるプロミスはその thenable をたどり、その結果を採用します。そうでなければ、返されるプロミスは与えられた値で解決されます。 + + 一般に、ある値がプロミスであるかどうかがわからない場合は、代わりに {{JSxRef("Promise.resolve", "Promise.resolve(value)")}} を使用し、返値をプロミスとして扱います。 + +## インスタンスメソッド + +マイクロタスクのキューやサービスを使用する方法については、[マイクロタスクのガイド](/ja/docs/Web/API/HTML_DOM_API/Microtask_guide "Microtask_guide")を参照してください。 + +- {{jsxref("Promise.prototype.catch()")}} + - : プロミスに拒否ハンドラーコールバックを追加し、コールバックが呼び出されたときの返値で解決する、または、プロミスが履行された場合は、元の履行結果で解決する + 新しいプロミスを返します。 +- {{jsxref("Promise.prototype.then()")}} + - : プロミスに履行ハンドラーと拒否ハンドラーを追加し、呼び出されたハンドラーの返値で解決する新しいプロミスを返します。プロミスが処理されなかった場合 (すなわち、関連するハンドラー `onFulfilled` または `onRejected` が関数ではない場合) は、元の解決値を返します。 +- {{jsxref("Promise.prototype.finally()")}} + - : プロミスにハンドラーを追加し、元のプロミスが解決されたときに解決される新しいプロミスを返します。このハンドラーは、成功か失敗かに関わらず、元のプロミスが完了したときに呼び出されます。 + +## 例 + +### 基本的な例 + +```js +let myFirstPromise = new Promise((resolve, reject) => { + // We call resolve(...) when what we were doing asynchronously was successful, and reject(...) when it failed. + // In this example, we use setTimeout(...) to simulate async code. + // In reality, you will probably be using something like XHR or an HTML5 API. + setTimeout( function() { + resolve("Success!") // Yay! Everything went well! + }, 250) +}) + +myFirstPromise.then((successMessage) => { + // successMessage is whatever we passed in the resolve(...) function above. + // It doesn't have to be a string, but if it is only a succeed message, it probably will be. + console.log("Yay! " + successMessage) +}); +``` + +### 多様な状況に対応した例 + +この例では、プロミス機能を使用するための多様なテクニックと、発生する可能性のある多様な状況を示しています。これを理解するには、まずコードブロックの一番下までスクロールして、プロミス連鎖を調べてください。最初のプロミスが提供されてから、プロミスの連鎖が続きます。この連鎖は `.then()` の呼び出しで構成され、通常は (必ずしもそうとは限りませんが) 最後に単一の `.catch()` があり、任意で `.finally()` が続きます。この例では、プロミス連鎖は独自に書かれた `new Promise()` コンストラクターによって開始されますが、実際には、プロミス連鎖は通常、プロミスを返す API 関数 (他の誰かが書いたもの) から開始されます。 + +関数 `tetheredGetNumber()` の例では、非同期呼び出しを設定している間、またはコールバック内で、またはその両方で `reject()` を使用してプロミスを生成することを示しています。 関数 `promiseGetWord()` は、API 関数がどのように自己完結型の方法でプロミスを生成して返すかを示しています。 + +関数 `troubleWithGetNumber()` は `throw()` で終わることに注意してください。これは、 ES6 のプロミス連鎖では、エラーが発生した後で、 "throw()" がなく、エラーが "fixed" であるようにみえても、すべての `.then()` のプロミスを通過するため、強制的に行われています。これは面倒なので、 `.then()` プロミスの連鎖全体で `rejectionFunc` を省略して、最終的な `catch()` で単一の `rejectionFunc` を使用するのが一般的です。 別の方法としては、特別な値を投げるという方法があります (この場合は "-999" ですが、カスタムのエラー種別の方が適切です)。 + +このコードは NodeJS で実行できます。実際にエラーが発生しているのを見ることで理解度が高まります。より多くのエラーを強制的に発生させるには、 `threshold` の値を変更します。 + +```js +"use strict"; + +// To experiment with error handling, "threshold" values cause errors randomly +const THRESHOLD_A = 8; // can use zero 0 to guarantee error + +function tetheredGetNumber(resolve, reject) { + try { + setTimeout( + function() { + const randomInt = Date.now(); + const value = randomInt % 10; + try { + if(value >= THRESHOLD_A) { + throw new Error(`Too large: ${value}`); + } + } catch(msg) { + reject(`Error in callback ${msg}`); + } + resolve(value); + return; + }, 500); + // To experiment with error at set-up, uncomment the following 'throw'. + // throw new Error("Bad setup"); + } catch(err) { + reject(`Error during setup: ${err}`); + } + return; +} + +function determineParity(value) { + const isOdd = value % 2 ? true : false ; + const parityInfo = { theNumber: value, isOdd: isOdd }; + return parityInfo; +} + +function troubleWithGetNumber(reason) { + console.error(`Trouble getting number: ${reason}`); + throw -999; // must "throw" something, to maintain error state down the chain +} + +function promiseGetWord(parityInfo) { + // The "tetheredGetWord()" function gets "parityInfo" as closure variable. + const tetheredGetWord = function(resolve,reject) { + const theNumber = parityInfo.theNumber; + const threshold_B = THRESHOLD_A - 1; + if(theNumber >= threshold_B) { + reject(`Still too large: ${theNumber}`); + } else { + parityInfo.wordEvenOdd = parityInfo.isOdd ? 'odd' : 'even'; + resolve(parityInfo); + } + return; + } + return new Promise(tetheredGetWord); +} + +(new Promise(tetheredGetNumber)) + .then(determineParity,troubleWithGetNumber) + .then(promiseGetWord) + .then((info) => { + console.log("Got: ",info.theNumber," , ", info.wordEvenOdd); + return info; + }) + .catch((reason) => { + if(reason === -999) { + console.error("Had previously handled error"); + } + else { + console.error(`Trouble with promiseGetWord(): ${reason}`); + } + }) + .finally((info) => console.log("All done")); +``` + +<h3 id="Advanced_Example">高度な例</h3> + +以下の例は `Promise` の仕組みを示したものです。 `testPromise()` メソッドは {{HTMLElement("button")}} をクリックする度に呼び出されます。`testPromise()` メソッドは、 {{domxref("WindowOrWorkerGlobalScope.setTimeout")}} を用いて、 1 秒から 3 秒のランダムな時間の後、メソッドがこれまでに呼ばれた回数で履行されるプロミスを作成します。 `Promise()` コンストラクターを使用してプロミスを生成します。 + +プロミスが履行されたことは、 {{JSxRef("Promise.prototype.then()","p1.then()")}} で設定されたコールバックによって記録されます。この記録から、メソッドの同期処理部分が、プロミスによる非同期処理からどのように分離されているかがわかります。 + +短時間に何度もボタンをクリックすると、さまざまなプロミスが次々と履行されていく様子を見ることもできます。 + +#### HTML + +```html +<button id="make-promise">プロミスを作成</button> +<div id="log"></div> +``` + +#### JavaScript + +```js +"use strict"; +let promiseCount = 0; + +function testPromise() { + let thisPromiseCount = ++promiseCount; + let log = document.getElementById('log'); + // 開始 + log.insertAdjacentHTML('beforeend', thisPromiseCount + ') 開始<br>'); + // 新しいプロミスを作成します。このプロミスで 1 から始まる数値のカウントを (3 秒の待ち時間の後に) 約束します + let p1 = new Promise((resolve, reject) => { + // プロミスを解決または拒否する機能を持つ実行関数が呼び出されます + log.insertAdjacentHTML('beforeend', thisPromiseCount + ') Promise コンストラクター<br>'); + // これは単に非同期にするための例に過ぎません + window.setTimeout(function() { + // プロミスを履行させます + resolve(thisPromiseCount); + }, Math.random() * 2000 + 1000); + }); + + // プロミスが解決されたときの処理を then() の呼び出しで定義します。 + // プロミスが拒否されたときの処理を catch() の呼び出しで定義しています。 + p1.then(function(val) { + // Log the fulfillment value + log.insertAdjacentHTML('beforeend', val + ') Promise 履行<br>'); + }).catch((reason) => { + // Log the rejection reason + console.log(`ここでは拒否されたプロミス (${reason}) を処理します。`); + }); + // 終了 + log.insertAdjacentHTML('beforeend', thisPromiseCount + ') Promise 生成<br>'); +} + +if ("Promise" in window) { + let btn = document.getElementById("make-promise"); + btn.addEventListener("click",testPromise); +} else { + log = document.getElementById('log'); + log.textContent = "ブラウザーが <code>Promise<code> インターフェイスに対応していないので、実行例が利用できません。"; +} +``` + +### 結果 + +{{EmbedLiveSample("Advanced_Example", "500", "200")}} + +<h3 id="Loading_an_image_with_XHR" name="Loading_an_image_with_XHR">XHR による画像の読み込み</h3> + +`Promise` と {{domxref("XMLHttpRequest")}} で画像を読み込む別の例は、 MDN GitHub <a href="https://github.com/mdn/js-examples/tree/master/promises-test">js-examples</a> リポジトリにあり、<a href="https://mdn.github.io/js-examples/promises-test/">動作を確認する</a>ことができます。それぞれの行のコメントで Promise と XHR の構造がよくわかるはずです。 + +## 仕様書 + +{{Specifications}} + +## ブラウザーの互換性 + +{{Compat}} + +## 関連情報 + +- `Promise` のポリフィルが [`core-js`](https://github.com/zloirock/core-js#ecmascript-promise) で利用できます +- [プロミスの使用](/ja/docs/Web/JavaScript/Guide/Using_promises) +- [Promises/A+ specification](https://promisesaplus.com/) +- [Venkatraman.R - JS Promise (Part 1, Basics)](https://medium.com/@ramsunvtech/promises-of-promise-part-1-53f769245a53) +- [Venkatraman.R - JS Promise (Part 2 - Using Q.js, When.js and RSVP.js)](https://medium.com/@ramsunvtech/js-promise-part-2-q-js-when-js-and-rsvp-js-af596232525c#.dzlqh6ski) +- [Venkatraman.R - Tools for Promises Unit Testing](https://tech.io/playgrounds/11107/tools-for-promises-unittesting/introduction) +- [Jake Archibald: JavaScript Promises: There and Back Again](https://www.html5rocks.com/en/tutorials/es6/promises/) +- [Domenic Denicola: Callbacks, Promises, and Coroutines – Asynchronous Programming Patterns in JavaScript](https://de.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript) +- [Matt Greer: JavaScript Promises ... In Wicked Detail](https://www.mattgreer.org/articles/promises-in-wicked-detail/) +- [Forbes Lindesay: promisejs.org](https://www.promisejs.org/) +- [Speed-polyfill to polyfill both promise availability and promise performance.](https://github.com/anonyco/SPromiseMeSpeedJS/blob/master/README.md) +- [Promise polyfill](https://github.com/jakearchibald/es6-promise/) +- [Udacity: JavaScript Promises](https://www.udacity.com/course/javascript-promises--ud898) diff --git a/files/ja/web/javascript/reference/global_objects/promise/then/index.html b/files/ja/web/javascript/reference/global_objects/promise/then/index.html index c75b748aad..f0ad7223d5 100644 --- a/files/ja/web/javascript/reference/global_objects/promise/then/index.html +++ b/files/ja/web/javascript/reference/global_objects/promise/then/index.html @@ -38,7 +38,7 @@ p.then(value => { <dt><code>onFulfilled</code> {{optional_inline}}</dt> <dd><code>Promise</code> が成功したときに呼び出される {{jsxref("Function")}} です。この関数は1つの引数、 <code>fulfillment value</code> を持ちます。これが関数ではない場合は、内部的に "Identity" 関数 (受け取った引数を返す関数) に置き換えられます。</dd> <dt><code>onRejected</code> {{optional_inline}}</dt> - <dd><code>Promise</code> が拒絶されたときに呼び出される {{jsxref("Function")}} です。この関数は1つの引数、 <code>rejection reason</code> を持ちます。これが関数ではない場合は、内部的に "Thrower" 関数 (引数として受け取ったエラーを投げる関数) に置き換えられます。</dd> + <dd><code>Promise</code> が拒否されたときに呼び出される {{jsxref("Function")}} です。この関数は1つの引数、 <code>rejection reason</code> を持ちます。これが関数ではない場合は、内部的に "Thrower" 関数 (引数として受け取ったエラーを投げる関数) に置き換えられます。</dd> </dl> <h3 id="Return_value" name="Return_value">返値</h3> @@ -48,10 +48,10 @@ p.then(value => { <ul> <li>値を返した場合、 <code>then</code> によって返される Promise は返値をその値として解決します。</li> <li>何も返さなかった場合、 <code>then</code> によって返される Promise は <code>undefined</code> の値で解決します。</li> - <li>エラーを投げた場合、 <code>then</code> によって返される Promise は、その値としてエラーを投げて拒絶されます。</li> + <li>エラーを投げた場合、 <code>then</code> によって返される Promise は、その値としてエラーを投げて拒否されます。</li> <li>すでに解決している Promise を返した場合、 <code>then</code> によって返される Promise は、その Promise の値をその値として返します。</li> - <li>すでに拒絶された Promise を返した場合、 <code>then</code> によって返される Promise は、その Promise の値をその値として拒絶されます。</li> - <li>他の <strong>pending</strong> 状態の Promise オブジェクトを返した場合、 <code>then</code> によって返された Promise の解決/拒絶は、ハンドラーによって返された Promise の解決/拒絶結果に依存します。また、 <code>then</code> によって返された Promise の解決値は、ハンドラーによって返された Promise の解決値と同じになります。</li> + <li>すでに拒否された Promise を返した場合、 <code>then</code> によって返される Promise は、その Promise の値をその値として拒否されます。</li> + <li>他の <strong>pending</strong> 状態の Promise オブジェクトを返した場合、 <code>then</code> によって返された Promise の解決/拒否は、ハンドラーによって返された Promise の解決/拒否結果に依存します。また、 <code>then</code> によって返された Promise の解決値は、ハンドラーによって返された Promise の解決値と同じになります。</li> </ul> <p>以下は、 <code>then</code> メソッドの非同期性を示す例です。</p> @@ -161,7 +161,7 @@ p2.then(function(value) { }); </pre> -<p><code>then</code> の引数として渡した関数が拒絶された Promise を返した場合や、例外 (エラー) が発生した場合は、拒絶された Promise を返します。</p> +<p><code>then</code> の引数として渡した関数が拒否された Promise を返した場合や、例外 (エラー) が発生した場合は、拒否された Promise を返します。</p> <pre class="brush: js notranslate">Promise.resolve() .then(() => { @@ -174,7 +174,7 @@ p2.then(function(value) { console.error('onRejected function called: ' + error.message); });</pre> -<p>その他の場合はすべて、<ruby>解決中<rp> (</rp><rt>resolving</rt><rp>) </rp></ruby>の Promise が返されます。次の例では、チェーン上の以前の Promise が拒絶されていても、最初の <code>then()</code> は解決中の Promise に含まれた <code>42</code> を返します。</p> +<p>その他の場合はすべて、<ruby>解決中<rp> (</rp><rt>resolving</rt><rp>) </rp></ruby>の Promise が返されます。次の例では、チェーン上の以前の Promise が拒否されていても、最初の <code>then()</code> は解決中の Promise に含まれた <code>42</code> を返します。</p> <pre class="brush: js notranslate">Promise.reject() .then(() => 99, () => 42) // onRejected returns 42 which is wrapped in a resolving Promise diff --git a/files/ja/web/javascript/reference/global_objects/webassembly/compilestreaming/index.html b/files/ja/web/javascript/reference/global_objects/webassembly/compilestreaming/index.html deleted file mode 100644 index e3048ea38f..0000000000 --- a/files/ja/web/javascript/reference/global_objects/webassembly/compilestreaming/index.html +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: WebAssembly.compileStreaming() -slug: Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming -translation_of: Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming ---- -<div>{{JSRef}} {{SeeCompatTable}}</div> - -<p><strong><code>WebAssembly.compileStreaming()</code></strong> 関数はソースのストリームから直接 {{jsxref("WebAssembly.Module")}} にコンパイルします。この関数はモジュールをインスタンス化する前にコンパイルする必要がある場合に役立ちます (そうでない場合は、{{jsxref("WebAssembly.instantiateStreaming()")}} 関数の仕様が推奨されます)。</p> - -<h2 id="構文">構文</h2> - -<pre class="syntaxbox">Promise<WebAssembly.Module> WebAssembly.compileStreaming(<em>source</em>);</pre> - -<h3 id="パラメータ">パラメータ</h3> - -<dl> - <dt><em>source</em></dt> - <dd>ストリーム、コンパイルする .wasm モジュールのソースコードを表す {{domxref("Response")}} オブジェクトか、それを fulfill するプロミス。 </dd> -</dl> - -<h3 id="戻り値">戻り値</h3> - -<p>解決時にコンパイルされたモジュールを表す {{jsxref("WebAssembly.Module")}} を渡す <code>Promise</code> 。</p> - -<h3 id="例外">例外</h3> - -<ul> - <li><code>bufferSource</code> が <a href="/ja/docs/Web/JavaScript/Typed_arrays">型付き配列</a> でない場合、 {{jsxref("TypeError")}} がスローされます。</li> - <li>失敗した場合、プロミスは {{jsxref("WebAssembly.CompileError")}} を持って棄却されます。</li> -</ul> - -<h2 id="例">例</h2> - -<p>次の例 (Github上のデモ <a href="https://github.com/mdn/webassembly-examples/blob/master/js-api-examples/compile-streaming.html">compile-streaming.html</a> と、<a href="https://mdn.github.io/webassembly-examples/js-api-examples/compile-streaming.html">動作例</a> を参照してください) では、ソースから直接 .wasm モジュールをストリームして、 {{jsxref("WebAssembly.Module")}} オブジェクトにコンパイルしています。<code>compileStreaming()</code> 関数は {{domxref("Response")}} オブジェクトを渡すプロミスを受け取るので、直接 {{domxref("WindowOrWorkerGlobalScope.fetch()")}} の呼び出し結果を渡すことができます。</p> - -<pre class="brush: js">var importObject = { imports: { imported_func: arg => console.log(arg) } }; - -WebAssembly.compileStreaming(fetch('simple.wasm')) -.then(module => WebAssembly.instantiate(module, importObject)) -.then(instance => instance.exports.exported_func());</pre> - -<p>結果として受け取ったモジュールインスタンスはその後 {{jsxref("WebAssembly.instantiate()")}} を使用してインスタンス化され、エクスポートされた関数が実行されます。</p> - -<h2 id="仕様">仕様</h2> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Specification</th> - <th scope="col">Status</th> - <th scope="col">Comment</th> - </tr> - </thead> - <tbody> - <tr> - <td>{{SpecName('WebAssembly Embedding', '#webassemblycompilestreaming', 'compileStreaming()')}}</td> - <td>{{Spec2('WebAssembly Embedding')}}</td> - <td>初回ドラフト定義</td> - </tr> - </tbody> -</table> - -<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザ実装状況</h2> - -<div> - - -<p>{{Compat("javascript.builtins.WebAssembly.compileStreaming")}}</p> -</div> - -<h2 id="関連情報">関連情報</h2> - -<ul> - <li><a href="/ja/docs/WebAssembly">WebAssembly</a> overview page</li> - <li><a href="/ja/docs/WebAssembly/Concepts">WebAssemblyのコンセプト</a></li> - <li><a href="/ja/docs/WebAssembly/Using_the_JavaScript_API">WebAssembly JavaScript APIを使用する</a></li> -</ul> diff --git a/files/ja/web/javascript/reference/global_objects/webassembly/compilestreaming/index.md b/files/ja/web/javascript/reference/global_objects/webassembly/compilestreaming/index.md new file mode 100644 index 0000000000..958c517cad --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/webassembly/compilestreaming/index.md @@ -0,0 +1,69 @@ +--- +title: WebAssembly.compileStreaming() +slug: Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming +tags: + - API + - JavaScript + - Method + - Object + - Reference + - WebAssembly + - compile + - compileStreaming + - streaming +browser-compat: javascript.builtins.WebAssembly.compileStreaming +translation_of: Web/JavaScript/Reference/Global_Objects/WebAssembly/compileStreaming +--- +{{JSRef}} + +**`WebAssembly.compileStreaming()`** 関数は {{jsxref("WebAssembly.Module")}} を直接、基礎的なソースのストリームからコンパイルします。この関数はモジュールをインスタンス化する前にコンパイルする必要がある場合に役立ちます (そうでない場合は、{{jsxref("WebAssembly.instantiateStreaming()")}} 関数の仕様が推奨されます)。 + +## 構文 + +```js +WebAssembly.compileStreaming(source) +``` + +### 引数 + +- _source_ + - : ストリーム、コンパイルする .wasm モジュールのソースコードを表す [`Response`](/ja/docs/Web/API/Response "Response は Fetch API のインターフェイスで、リクエストのレスポンスを表します。") オブジェクトか、それを満足するプロミスです。 + +### 返値 + +`Promise` で、コンパイルされたモジュールを表す {{jsxref("WebAssembly.Module")}} に解決します。</p> + +### 例外 + +- `bufferSource` が[型付き配列](/ja/docs/Web/JavaScript/Typed_arrays)でない場合、 {{jsxref("TypeError")}} が発生します。 +- 失敗した場合、プロミスは {{jsxref("WebAssembly.CompileError")}} をで棄却されます。 + +## 例 + +### ストリーミングのコンパイル + +次の例 (Github上のデモ [compile-streaming.html](https://github.com/mdn/webassembly-examples/blob/master/js-api-examples/compile-streaming.html) と、[動作例](https://mdn.github.io/webassembly-examples/js-api-examples/compile-streaming.html)を参照してください) では、ソースから直接 .wasm モジュールをストリームして、 {{jsxref("WebAssembly.Module")}} オブジェクトにコンパイルしています。`compileStreaming()` 関数は [`Response`](/ja/docs/Web/API/Response "Response は Fetch API のインターフェイスで、リクエストのレスポンスを表します。") オブジェクトを渡すプロミスを受け取るので、直接 {{domxref("WindowOrWorkerGlobalScope.fetch()")}} の呼び出し結果を渡すことができます。 + +```js +var importObject = { imports: { imported_func: arg => console.log(arg) } }; + +WebAssembly.compileStreaming(fetch('simple.wasm')) +.then(module => WebAssembly.instantiate(module, importObject)) +.then(instance => instance.exports.exported_func()); +``` + +結果として受け取ったモジュールインスタンスはその後 {{jsxref("WebAssembly.instantiate()")}} を使用してインスタンス化され、エクスポートされた関数が実行されます。 + +## 仕様書 + +{{Specifications}} + +## ブラウザーの互換性 + +{{Compat}} + +## 関連情報 + +- [WebAssembly](/ja/docs/WebAssembly) 概要ページ +- [WebAssembly の概念](/ja/docs/WebAssembly/Concepts) +- [WebAssembly JavaScript API の使用](/ja/docs/WebAssembly/Using_the_JavaScript_API) diff --git a/files/ja/web/javascript/reference/operators/index.html b/files/ja/web/javascript/reference/operators/index.html index ce93a79806..aa1fde203b 100644 --- a/files/ja/web/javascript/reference/operators/index.html +++ b/files/ja/web/javascript/reference/operators/index.html @@ -39,7 +39,7 @@ translation_of: Web/JavaScript/Reference/Operators <dt>{{JSxRef("Operators/async_function", "async function")}}</dt> <dd><code>async function</code> は非同期の関数式を定義します。</dd> <dt>{{JSxRef("Operators/await", "await")}}</dt> - <dd>非同期関数式の停止/再開と、プロミスの解決/拒絶を待ちます。</dd> + <dd>非同期関数式の停止/再開と、プロミスの解決/拒否を待ちます。</dd> <dt>{{JSxRef("Global_Objects/Array", "[]")}}</dt> <dd>配列初期化子またはリテラル構文です。</dd> <dt>{{JSxRef("Operators/Object_initializer", "{}")}}</dt> |