--- 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> <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>