Async Functionとは非同期処理を行う関数を定義する構文です。
Async Functionは通常の関数とは異なり、必ずPromise
インスタンスを返す関数を定義する構文です。
Async Functionは次のように関数の前にasync
をつけることで定義できます。
このdoAsync
関数は常にPromise
インスタンスを返します。
async function doAsync() {
return "値";
}
// doAsync関数はPromiseを返す
doAsync().then((value) => {
console.log(value); // => "値"
});
Async Functionではreturn
した値の代わりに、Promise.resolve(返り値)
のように返り値をラップしたPromise
インスタンスを返します。
そのため、このAsync Functionは次のように書いた場合と同じ意味になります。
// 通常の関数でPromiseインスタンスを返している
function doAsync() {
return Promise.resolve("値");
}
doAsync().then((value) => {
console.log(value); // => "値"
});
またAsync Function内ではawait
式というPromiseの非同期処理が完了するまで待つ構文が利用できます。
await
式を使うことで非同期処理を同期処理のように扱えるため、Promiseチェーンで実現していた処理の流れを読みやすくかけます。
Async Functionとawait
式の大まかな動きをイメージするために、まずはPromise APIで書いたものと比較してみます。
ここでは、XHRの現代的なバージョンである Fetch API を使います。Fetch APIは指定したURLのリソースを読み書きでき、デフォルトでES Promisesに対応しています。
次のサンプルコードでは、https://azu.github.io/promises-book/json/book.json
というURLからJSONデータを取得して、title
プロパティを取り出すgetBookTitle
関数を実装していきます。
取得するhttps://azu.github.io/promises-book/json/book.json
は次のような内容になっています。
link:../json/book.json[role=include]
まずは、Fetch APIを使ってfetchBookTitle
関数で取得したタイトルをコンソールに出力してみます。
fetch
メソッドはPromiseを返します。このPromiseインスタンスはリクエストのレスポンスを表すResponse
オブジェクトでresolveされます。
Response#json
メソッドもPromiseを返します。このPromiseインスタンスは取得したリソースをJSONとしてパースしたオブジェクトでresolveされます。
fetchBookTitle
関数は、次のようにfetch
メソッドで取得したJSONのtitle
プロパティでresolveされるPromiseインスタンスを返します。
function fetchBookTitle() {
// Fetch APIは指定URLのリソースを取得しPromiseを返す関数
return fetch("https://azu.github.io/promises-book/json/book.json").then((res) => {
return res.json(); // レスポンスをJSON形式としてパースする
}).then((json) => {
return json.title; // JSONからtitleプロパティを取り出す
});
}
function main() {
// `fetchBookTitle`関数は、取得したJSONの`title`プロパティでresolveされる
fetchBookTitle().then((title) => {
console.log(title); // => "JavaScript Promiseの本"
});
}
main();
次は、同様の処理をAsync Functionとawait
式で実装してみます。
ここではまだ挙動を理解しなくても問題ありませんが、
Promise APIを使っていた場合に比べて、then
メソッドやコールバック関数がなくなっていることが分かります。
// `async`をつけて`fetchBookTitle`関数をAsync Functionとして定義
async function fetchBookTitle() {
// リクエストしてリソースを取得する
const res = await fetch("https://azu.github.io/promises-book/json/book.json");
// レスポンスをJSON形式としてパースする
const json = await res.json();
// JSONからtitleプロパティを取り出す
return json.title;
}
// `async`をつけて`main`関数をAsync Functionとして定義
async function main() {
// `await`式で`fetchBookTitle`の非同期処理が完了するまで待つ
// `fetchBookTitle`がresolveした値が返り値になる
const title = await fetchBookTitle();
console.log(title); // => "JavaScript Promiseの本"
}
main();
Async FunctionではPromiseの状態が変化するまで待つawait
式という機能を利用できます。
Promiseでは結果をthen
メソッドのコールバック関数で取得していたのが、await
式の右辺にあるPromiseのresolveされた値が左辺の変数へと代入されます。そのため、Async Functionとawait
式を使うことで非同期処理をまるで同期処理のように書けます。
この章では、このAsync Functionとawait
式について詳しく見ていきます。
重要なこととしてAsync FunctionはPromiseの上に作られた構文です。 そのためAsync Functionを理解するには、Promiseを理解する必要があることに注意してください。