ES2017では、Promiseをさらに扱いやすくするためにasync
/await
構文が導入されました。async
関数の中でawait
式を使うと、Promiseの完了を待ってその結果を取得するまで関数の実行を一時停止し、まるで同期処理のように非同期処理を書けます。
async
を付けた関数は常にPromiseを返すようになります(関数内部で暗黙的にPromiseが生成されます)。await
はそのPromiseが解決されるまで待ち、解決値を返します。await
はasync
関数の中でしか使用できない制約がありますが、その代わりasync
関数内では直列的なコードで非同期処理を順序よく書くことが可能です。
本章では、前章で書いたPromiseの例をasync/await
を用いた書き方に書き換えてみます。
JavaScriptでasync/await
を使った例を示します。先ほどのfetchData
(Promiseを返す関数)をそのまま利用し、async
関数内でawait
しています。
async function processData() {
try {
console.log("データ取得開始");
const result = await fetchData(); // fetchData()のPromiseが解決するまで待機
console.log(result.message); // "データ取得成功"
console.log(result.data); // [1, 2, 3]
// ここでresultを使った後続の処理が書ける
} catch (error) {
console.error("エラーが発生しました:", error);
} finally {
console.log("非同期処理が終了(async/await)");
}
}
processData(); // async関数はPromiseを返すが、ここでは即時実行
解説:
async function processData()
と宣言することで、この関数は必ずPromiseを返すようになります。実際には関数がreturnで値(または何も)返した場合、その値で解決するPromiseが戻り、エラーが発生してcatchされなかった場合はrejectされたPromiseが返ります。await fetchData()
の行では、前章で定義したfetchData()
の完了を待ち、その結果result
に代入します。await
している間、非同期処理が完了するまでprocessData
関数の実行は一時停止し、完了後に次の行に進みます。
この間JavaScript全体の実行がブロックされるわけではなく、他のイベントループは回っています。await
はあくまでprocessData
関数内の流れを一時停止するものです。そのため、async/await
を使っても非同期処理であることに変わりはなく、内部ではPromiseが動いています。
try...catch
構文を用いることで、await
した呼び出しでエラー(Promiseのreject)が発生した場合にcatch
ブロックで捕捉できます。.then().catch()
チェーンの場合と同様に、例外処理を行えるわけです。finally
ブロックも用いることができ、Promiseの.finally
と同様の役割を果たします。
このようにasync/await
を使うことで、Promiseチェーンで書いていた非同期処理をより直感的な手続き型のコードに変換できます。特に複数の非同期処理を順番に行う場合や、条件分岐を交えながら非同期処理を記述する場合に、async/await
は可読性と保守性を向上させます。