aboutsummaryrefslogtreecommitdiff
path: root/files/ja/web/javascript/reference/statements/async_function
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
commit33058f2b292b3a581333bdfb21b8f671898c5060 (patch)
tree51c3e392513ec574331b2d3f85c394445ea803c6 /files/ja/web/javascript/reference/statements/async_function
parent8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff)
downloadtranslated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip
initial commit
Diffstat (limited to 'files/ja/web/javascript/reference/statements/async_function')
-rw-r--r--files/ja/web/javascript/reference/statements/async_function/index.html261
1 files changed, 261 insertions, 0 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
new file mode 100644
index 0000000000..4c4032c50d
--- /dev/null
+++ b/files/ja/web/javascript/reference/statements/async_function/index.html
@@ -0,0 +1,261 @@
+---
+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 =&gt; {
+ setTimeout(function() {
+ resolve("slow")
+ console.log("slow promise is done")
+ }, 2000)
+ })
+}
+
+function resolveAfter1Second() {
+ console.log("starting fast promise")
+ return new Promise(resolve =&gt; {
+ 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) =&gt; {
+ 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()=&gt;console.log(await resolveAfter2Seconds()))(),
+ (async()=&gt;console.log(await resolveAfter1Second()))()
+ ])
+}
+
+// この関数はエラーハンドリングをしていません。後述の注意書きを参照してください。
+function parallelPromise() {
+ console.log('==PARALLEL with Promise.then==')
+ resolveAfter2Seconds().then((message)=&gt;console.log(message))
+ resolveAfter1Second().then((message)=&gt;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 =&gt; {
+ return downloadFallbackData(url) // returns a promise
+ })
+ .then(v =&gt; {
+ 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>
+<div class="hidden">このページの互換性一覧表は構造化データから生成されています。データに協力していただけるのであれば、 <a class="external" href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> をチェックアウトしてプルリクエストを送信してください。</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>