Get to know MDN better
このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。
この機能は広く実装されており、多くのバージョンの端末やブラウザーで動作します。2017年4月以降、すべてのブラウザーで利用可能です。
async function 宣言は、与えられた名前で新しい非同期関数のバインドを作成します。その関数の本体の中では await キーワードを使うことができ、ます。async および await キーワードを使用することで、プロミスベースの非同期の動作を、プロミスチェーンを明示的に構成する必要なく、よりすっきりとした方法で書くことができます。
非同期関数は async function 式を使用して定義することもできます。
メモ: 改行を async と function の間に入れてはいけません。そうしないとセミコロンが自動的に挿入され、async が識別子となり、残りが function 宣言となります。
関数の名前です。
param 省略可関数の正式な引数の名前です。引数の構文については、関数リファレンスを参照してください。
statements 省略可関数の本体を構成する文です。await の仕組みを使用することができます。
async function 宣言は、AsyncFunction オブジェクトを作成します。非同期関数が呼び出されるたびに、新しいプロミス (Promise) が返され、非同期関数によって返された値で解決されます。または、非同期関数内で捕捉されなかった例外で拒否されます。
非同期関数には、 await 式を置くことができます。 await 式は返されたプロミスが履行されるか拒否されるまで実行を中断することで、プロミスを返す関数をあたかも同期しているかのように動作させます。プロミスの解決済みの値は、await 式の返値として扱われます。async と await を使用すると、非同期コードに通常の try / catch ブロックを使用することができます。
メモ: キーワード await は、通常の JavaScript コード内の非同期関数内でのみ有効です。非同期関数の外で使用した場合は SyntaxError が発生します。
await は JavaScript モジュールでは単独で使用することができます。
メモ: async/await の目的は、プロミスベースの API を利用するのに必要な構文を簡素化することです。 async/await の動作は、ジェネレーターとプロミスの組み合わせに似ています。
非同期関数は常にプロミスを返します。非同期関数の返値が明示的にプロミスでない場合は、暗黙的にプロミスでラップされます。
例えば、以下のコードを考えてください。
これは、次のコードに似ています。
たとえ非同期関数の返値が Promise.resolve でラップされているかのように振る舞うとしても、それらは同等ではないことに注意してください。非同期関数は別の参照を返しますが、Promise.resolve は指定された値がプロミスであれば同じ参照を返します。プロミスと非同期関数の返値の等価性を調べようとすると、問題が発生する可能性があります。
非同期関数の本体は、0 個以上の await 式で分割されていると考えることができます。最上位のコードは、最初の await 式(ある場合)まで含めて同期的に実行されます。この方法では、await 式のない非同期関数は同期的に実行されます。しかし、関数本体内に await 式がある場合、非同期関数は常に非同期的に完了します。
例:
これは次のものと等価です。
それぞれの await 式の後のコードは、.then コールバックの中に存在すると考えることができます。このようにして、関数を再帰的に実行するたびに、プロミスチェーンが徐々に構築されていきます。返値はチェーンの最後のリンクになります。
次の例では、 2 つのプロミスを連続して待ち受けます。関数 foo の処理は 3 段階に分かれています。
プロミスチェーンが一度に構築されないことに注意してください。プロミスチェーンは、非同期関数に制御を渡したり戻したりしながら、段階的に構築されていきます。そのため、同時並行の非同期処理を行う際には、エラー処理の動作に注意しなければなりません。
例えば、以下のコードでは、プロミスチェーンの先に .catch ハンドラーが設定されていたとしても、未処理のプロミス拒否エラーが発生します。これは、p1 から制御が戻るまで、p2 がプロミスチェーンに「配線」されないためです。
async function 宣言は、function 宣言と似た挙動をします。つまり、巻き上げによりスコープの先頭に移動し、スコープ内のどこからでも呼び出すことができます。また、特定のコンテキストでのみ再宣言することができます。
sequentialStart では、最初の await のために実行が 2 秒間待機し、 2 つ目の await のためにさらに 1 秒間待機します。 2 つ目のタイマーは最初のタイマーが起動している間は作成されません。コードは 3 秒後に終了します。
sequentialWait では、両方のタイマーが作成され、両方とも await される、すなわち待機させられます。タイマーは同時に実行されているため、 3 秒後ではなく 2 秒後に、すなわち最も遅いタイマーにあわせて終了します。 しかし、 await の呼び出しは依然として逐次処理であり、これは 2 つ目の await が 1 つ目の終了まで待つことを意味します。このケースでは、最も速いタイマーが最も遅いタイマーのあとに処理されることになります。
複数の処理を安全に並行に実行したい場合は、Promise.all() または Promise.allSettled() の呼び出しで待つ必要があります。
警告: 関数 sequentialWait と concurrent1 は機能的に同等ではありません。
sequentialWait では、プロミス fast がプロミス slow の履行よりも前に拒否された場合、呼び出し元が catch 節を構成しているかどうかにかかわらず、プロミスの拒否が処理されないというエラーが発生します。
concurrent1 では、Promise.all がプロミスチェーンを一括して配線します。つまり、操作はプロミスの拒否の順番に関係なくすばやく失敗し、エラーは構成されたプロミスチェーン内で常に発生するため、通常の方法で捕捉することができます。
Promise を返す API はプロミスチェーンを返し、関数を複数の部品に分割できます。次のコードを想定してください。
次のように 1 つの非同期関数に書き換えることができます。
他にも、 catch() によってプロミスを連鎖させることができます。
2 番目の例では、有効であるにもかかわらず、await 文が return キーワードの後にないことに注意してください。非同期関数の返値は、(この例のように)既にプロミスになっていない場合、暗黙的に Promise.resolve でラップされるからです。
| ECMAScript® 2027 Language Specification # sec-async-function-definitions |
ブラウザー互換性一覧表を表示するには、JavaScript を有効にしてください。
より良いインターネットのための青写真。
このコンテンツの一部は、©1998–2026 個人の mozilla.org 協力者です。コンテンツはクリエイティブ・コモンズ・ライセンスのもとで利用できます。