diff options
author | Masahiro FUJIMOTO <mfujimot@gmail.com> | 2021-09-12 01:52:23 +0900 |
---|---|---|
committer | Masahiro FUJIMOTO <mfujimot@gmail.com> | 2021-09-19 23:57:05 +0900 |
commit | f72358bab2839cbc638a1adbe331ff37cafd4cd5 (patch) | |
tree | eaca2e39220f28a0c39c7cdbe93678f4f552cf91 /files/ja/web/javascript/reference/statements/async_function/index.html | |
parent | 68a0467b225cdcf072526490374d29a21977e8a1 (diff) | |
download | translated-content-f72358bab2839cbc638a1adbe331ff37cafd4cd5.tar.gz translated-content-f72358bab2839cbc638a1adbe331ff37cafd4cd5.tar.bz2 translated-content-f72358bab2839cbc638a1adbe331ff37cafd4cd5.zip |
Statements/async_function を同期
- 2021/09/07 時点の英語版に同期
Diffstat (limited to 'files/ja/web/javascript/reference/statements/async_function/index.html')
-rw-r--r-- | files/ja/web/javascript/reference/statements/async_function/index.html | 259 |
1 files changed, 0 insertions, 259 deletions
diff --git a/files/ja/web/javascript/reference/statements/async_function/index.html b/files/ja/web/javascript/reference/statements/async_function/index.html deleted file mode 100644 index 2c708ddbc7..0000000000 --- a/files/ja/web/javascript/reference/statements/async_function/index.html +++ /dev/null @@ -1,259 +0,0 @@ ---- -title: 非同期関数 -slug: Web/JavaScript/Reference/Statements/async_function -tags: - - Example - - Function - - JavaScript - - Language feature - - Statement - - 文 - - 言語機能 - - 関数 -translation_of: Web/JavaScript/Reference/Statements/async_function ---- -<div>{{jsSidebar("Statements")}}</div> - -<p><span class="seoSummary"><code><strong>async function</strong></code> 宣言は、 <strong>非同期関数</strong> — {{jsxref("Global_Objects/AsyncFunction","AsyncFunction")}} オブジェクトである関数を定義します。非同期関数は<a href="/ja/docs/Web/JavaScript/EventLoop">イベントループ</a>を介して他のコードとは別に実行され、結果として暗黙の {{jsxref("Promise")}} を返します。ただし、非同期関数を使用したコードの構文および構造は、通常の同期関数と似たものになります。</span></p> - -<div class="noinclude"> -<p>{{jsxref("Operators/async_function", "async function 式", "", 1)}} を使用して非同期関数を定義することもできます。</p> -</div> - -<div>{{EmbedInteractiveExample("pages/js/statement-async.html", "taller")}}</div> - -<div class="hidden">このインタラクティブデモのソースは GitHub のリポジトリに格納されています。インタラクティブデモプロジェクトに協力したい場合は、 <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> をクローンしてプルリクエストを送ってください。</div> - -<h2 id="Syntax" name="Syntax">構文</h2> - -<pre class="syntaxbox notranslate">async function <var>name</var>([<var>param</var>[, <var>param</var>[, ...<var>param</var>]]]) { - <var>statements</var> -} -</pre> - -<h3 id="Parameters" name="Parameters">引数</h3> - -<dl> - <dt><code><var>name</var></code></dt> - <dd>関数名。</dd> - <dt><code><var>param</var></code></dt> - <dd>関数に渡す引数名。</dd> - <dt><code><var>statements</var></code></dt> - <dd>関数の本体を構成する文。</dd> -</dl> - -<h3 id="Return_value" name="Return_value">返値</h3> - -<p>{{jsxref("Promise")}} で、非同期関数から返される値で解決するか、または非同期関数内の捕捉されなかった例外で拒否します。</p> - -<h2 id="Description" name="Description">解説</h2> - -<p>非同期関数は、 {{jsxref("Operators/await", "await")}} 式を含むことができます。これは非同期関数の実行を一時停止し、 <code>Promise</code> の解決を待ちます。そして非同期関数の実行を再開し、解決された値を返します。</p> - -<p><strong>キーワード <code>await</code> は、非同期関数の中でのみ有効です。</strong>非同期関数の外で使用した場合は {{jsxref("SyntaxError")}} となります。</p> - -<p>非同期関数が一時停止している間、呼び出し側の関数は実行が続きます (非同期関数から返される暗黙の Promise を受け取ります)。</p> - -<div class="note"> -<p><code>async</code>/<code>await</code> の目的は、 Promise を同期的に使用する動作を簡素化し、 <code>Promise</code> のグループに対して何らかの動作を実行することです。 <code>Promise</code> が構造化コールバックに似ているのと同様に、 <code>async</code>/<code>await</code> はジェネレーターと Promise を組み合わせたものに似ています。</p> -</div> - -<h2 id="Examples" name="Examples">例</h2> - -<h3 id="Simple_example" name="Simple_example">シンプルな例</h3> - -<pre class="brush: js notranslate">function resolveAfter2Seconds() { - console.log("starting slow promise") - return new Promise(resolve => { - setTimeout(function() { - resolve("slow") - console.log("slow promise is done") - }, 2000) - }) -} - -function resolveAfter1Second() { - console.log("starting fast promise") - return new Promise(resolve => { - setTimeout(function() { - resolve("fast") - console.log("fast promise is done") - }, 1000) - }) -} - -async function sequentialStart() { - console.log('==SEQUENTIAL START==') - - // 1. ここは即時実行される - const slow = await resolveAfter2Seconds() - console.log(slow) // 2. ここは 1. の2秒後に実行される - - const fast = await resolveAfter1Second() - console.log(fast) // 3. ここは 1. の3秒後に実行される -} - -async function concurrentStart() { - console.log('==CONCURRENT START with await=='); - const slow = resolveAfter2Seconds() // 即時実行 - const fast = resolveAfter1Second() // 即時実行 - - // 1. ここは即時実行される - console.log(await slow) // 2. ここは 1. の2秒後に実行される - console.log(await fast) // 3. ここは 1. の2秒後(2.の直後)に実行される -} - -function concurrentPromise() { - console.log('==CONCURRENT START with Promise.all==') - return Promise.all([resolveAfter2Seconds(), resolveAfter1Second()]).then((messages) => { - console.log(messages[0]) // slow - console.log(messages[1]) // fast - }) -} - -async function parallel() { - console.log('==PARALLEL with await Promise.all==') - - // 2つの jobs を並列に実行し両方が完了するのを待つ - await Promise.all([ - (async()=>console.log(await resolveAfter2Seconds()))(), - (async()=>console.log(await resolveAfter1Second()))() - ]) -} - -// この関数はエラーハンドリングをしていません。後述の注意書きを参照してください。 -function parallelPromise() { - console.log('==PARALLEL with Promise.then==') - resolveAfter2Seconds().then((message)=>console.log(message)) - resolveAfter1Second().then((message)=>console.log(message)) -} - -sequentialStart() // 2秒後に "slow" をログ出力し、その1秒後に "fast" をログ出力する - -// 見やすくするため setTimeout で直前の処理が終わるのを待つ -setTimeout(concurrentStart, 4000) // 2秒後に "slow" と "fast" をログ出力する - -// 直前の処理を待つ -setTimeout(concurrentPromise, 7000) // concurrentStart と同様 - -// 直前の処理を待つ -setTimeout(parallel, 10000) // 本当に並列処理となるため1秒後に "fast" とログ出力し、その1秒後に "slow" とログ出力する - -// 直前の処理を待つ -setTimeout(parallelPromise, 13000) // parallel と同様 -</pre> - -<h4 id="await_and_parallelism" name="await_and_parallelism">await と並列性</h4> - -<p><code>sequentialStart</code> では、最初の <code>await</code> のために実行が 2 秒間待機し、 2 つ目の <code>await</code> のためにさらに 1 秒間待機します。 2 つ目のタイマーは最初のタイマーが起動している間は作成されません。コードは 3 秒後に終了します。</p> - -<p><code>concurrentStart</code> では、両方のタイマーが作成され、両方とも <code>await</code> される、すなわち待機させられます。タイマーは同時に実行されているため、 3 秒後ではなく 2 秒後に、すなわち最も遅いタイマーにあわせて終了します。<br> - しかし、 <code>await</code> の呼び出しは依然として逐次処理であり、これは 2 つ目の <code>await</code> が 1 つ目の終了まで待つことを意味します。このケースでは、最も速いタイマーが最も遅いタイマーのあとに処理されることになります。</p> - -<p>もし複数の処理を完全に並列に実行したい場合は、上記コード中の <code>parallel</code> のように <code>await Promise.all([job1(), job2()])</code> を使わなければなりません。</p> - -<div class="warning"> -<h4 id="asyncawait_vs_Promise.then_and_error_handling" name="asyncawait_vs_Promise.then_and_error_handling">async/await と Promise.then およびエラー処理</h4> - -<p>多くの非同期関数は Promise を用いて通常の関数として書くことができます。しかし <code>async</code> 関数はエラー処理において少し簡単です。</p> - -<p><code>concurrentStart</code>と<code>concurrentPromise</code>のどちらも関数としては同値です。</p> - -<ul> - <li><code>concurrentStart</code> では、 <code>await</code> されたいずれかの関数呼び出しが失敗すれば、例外は自動的にキャッチされ、非同期関数の実行が中断され、暗黙的に返される Promise を経由してエラーが呼び出し元へ伝えられます。</li> - <li>同じことが Promise の場合にも起こり、関数は、関数の完了をとらえて戻ってくる <code>Promise</code> の面倒を見なければなりません。これは <code>concurrentPromise</code> では <code>Promise.all([]).then()</code> が返す Promise を <code>return</code> することを意味します。実は、この例の前のバージョンはこれをやり忘れていました!</li> -</ul> - -<p>しかしながら非同期関数も誤ってエラーを飲み込んでしまうことがあります。</p> - -<p>上記の <code>parallel</code> という非同期関数を例にしてみましょう。もしこれが <code>Promise.all([])</code> 呼び出しの結果を <code>await</code> (もしくは <code>return</code>) しなければ、任意のエラーは伝わりません。</p> - -<p><code>parallelPromise</code> の例は簡潔に見えるものの、エラーをまったくハンドルしていません!同じことをするには、やはり <code>return Promise.all[()]</code> が必要になります。</p> -</div> - -<h3 id="Rewriting_a_promise_chain_with_an_async_function" name="Rewriting_a_promise_chain_with_an_async_function">promise チェーンをasync function で 書き換える</h3> - -<p>Promise を返す API は Promise チェーンで解決され、関数を複数の部品に分割できます。次のコードを想定してください。</p> - -<pre class="brush: js notranslate">function getProcessedData(url) { - return downloadData(url) // returns a promise - .catch(e => { - return downloadFallbackData(url) // returns a promise - }) - .then(v => { - return processDataInWorker(v) // returns a promise - }) -} -</pre> - -<p>次のように 1 つの <code>async</code> 関数に書き直すことができます。</p> - -<pre class="brush: js notranslate">async function getProcessedData(url) { - let v - try { - v = await downloadData(url) - } catch(e) { - v = await downloadFallbackData(url) - } - return processDataInWorker(v) -} -</pre> - -<p>上記の例では、 <code>return</code> ステートメント上に <code>await</code> ステートメントがないことに注目してください。なぜなら、<code>async function</code> の返値は暗黙的に {{jsxref("Promise.resolve")}} でラップされているからです。</p> - -<div class="blockIndicator note"> -<h4 id="return_await_promiseValue_vs._return_promiseValue" name="return_await_promiseValue_vs._return_promiseValue">return await promiseValue と return promiseValue</h4> - -<p>返値が {{jsxref("Promise.resolve")}} で暗黙にラッピングされるとはいえ、 <code>return await promiseValue</code> が <code>return promiseValue</code> と機能的に等価である訳ではありません。</p> - -<p>上記のコードを以下のように書き直したと想像してください。これは <code>processDataInWorker</code> がエラーで拒否した場合に <code>null</code> を返します。</p> - -<pre class="brush: js notranslate">async function getProcessedData(url) { - let v - try { - v = await downloadData(url) - } catch(e) { - v = await downloadFallbackData(url) - } - try { - return await processDataInWorker(v) // Note the `return await` vs. just `return` - } catch (e) { - return null - } -} -</pre> - -<p><code>return processDataInWorker(v)</code> と記述すると、 <code>processDataInWorker(v)</code> が拒否した場合に <code>null</code> に解決されるのではなく、関数が返した {{jsxref("Promise")}} が拒否されてしまいます。</p> - -<p>これは、 <code>return foo;</code> と <code>return await foo;</code> の微妙な違いを強調しています。 - <code>return foo</code> はすぐに <code>foo</code> を返し、 <code>foo</code> が拒否する Promise であっても例外を発生させません。 <code>return await foo</code> は、それが Promise であれば <code>foo</code> が解決するか拒否するかを待ち、拒否した場合は<strong>返す前</strong>に例外を発生させます。</p> -</div> - -<h2 id="Specifications" name="Specifications">仕様書</h2> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">仕様書</th> - </tr> - </thead> - <tbody> - <tr> - <td>{{SpecName('ESDraft', '#sec-async-function-definitions', 'async function')}}</td> - </tr> - </tbody> -</table> - -<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2> - -<div> -<p>{{Compat("javascript.statements.async_function")}}</p> -</div> - -<h2 id="See_also" name="See_also">関連情報</h2> - -<ul> - <li>{{jsxref("Operators/async_function", "async function expression")}}</li> - <li>{{jsxref("AsyncFunction")}} オブジェクト</li> - <li>{{jsxref("Operators/await", "await")}}</li> - <li><a href="http://innolitics.com/10x/javascript-decorators-for-promise-returning-functions/">"innolitics.com" の "Decorating Async Javascript Functions"</a></li> -</ul> |