async, await とは
Javascript における async
, await
とは、Promise
を使った非同期処理を暗黙的に扱うことで、同期的なコードのような書き方で非同期処理を記述することができるようにするための構文です。
Javascript における非同期処理は Promise を使うことで、コールバック地獄を回避できるようになりましたが、代わりに Promise オブジェクトを生成しなければなりません。メソッドチェーンを使っていい感じに記述できるようになりましたが、これをさらに簡潔に書けるようにするために async
, await
の構文を使うことができます。
async
, await
は見えないところで Promise
を使っているので、まずは Promise
についてしっかりと理解してから async
, await
に進みましょう。
MDNには次のようにあります。
async/await 関数の目的は、 promise を同期的に使用する動作を簡素化し、 Promise のグループに対して何らかの動作を実行することです。 Promise が構造化コールバックに似ているのと同様に、 async/await はジェネレータと promise を組み合わせたものに似ています。
async
async
は、関数定義の頭につけることでその関数を実行する Promise を返します。この関数を async関数 と呼びます。async関数は return値にかかわらず、必ず Promise を返します。
async function asyncFunction(x) {
return x;
}
function promiseFunction(x) {
return new Promise(function(resolve, reject) {
try {
resolve(x);
} catch (error) {
reject(error);
}
});
}
上のサンプルで定義している2つの関数は同じような意味になります。async
を付けた関数は Promise を返し、その戻り値を Promise が解決した際(resolve
)の値とします。また、関数内部でエラーが発生した際にはそのエラーを reject
します。
実態はPromiseを返しているのですが、Promiseオブジェクト生成の記述が簡略化され、タイプ数もネスト数も減っていることがわかります。
また、async関数の内部では await
を使うことができます。
await
await
は Promise の解決を待ち、その値を取り出してくれます。Promise が reject された場合にはその値をスローします。
// 2秒後に1加算
function promiseIncrement(num) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(num + 1);
}, 2000);
});
}
async function asyncFunction(x) {
// await で Promise の解決を待つ
const n = await promiseIncrement(0);
console.log(n); // Promiseオブジェクトではなく 1 になる
}
asyncFunction();
console.log('console end ...');
// console end ...
// 1
上記例では async関数内で await
を使っています。Promise が解決するまで async関数内では await
の位置で処理が止まることが確認できます。Promiseが解決された後に次の処理に移るので、n には処理結果の 1 が入っていることが確認できます(await
がついていないと Promise オブジェクトがそのまま入っています)。
実際にすべての処理が止まるわけではなく、あくまで async関数内の await
部分で止まって見えるだけです。async関数自体は Promise オブジェクトを返すので、すぐに次の処理に移り、最後のコンソール出力は当然すぐに実行されます。
async, await で並列処理を実行する
複数のPromiseを並列で実行する場合、すべてを起動してから await
しないと逐次実行されて並列にならないので注意する必要があります。
以下の例では、2秒かかる処理を3つ実行する例です。都度 await
をつけて実行すると6秒かかりますが、すべての Promise を起動してから それぞれ await
することで並列で動いてくれるので 2秒で処理が完了します。
// 2秒後に値を返す
function getNum(num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num);
}, 2000);
});
}
// 6秒後に出力
async function f1() {
const n1 = await getNum(1);
const n2 = await getNum(2);
const n3 = await getNum(3);
console.log(n1, n2, n3);
}
// 2秒後に出力
async function f2() {
const p1 = getNum(1);
const p2 = getNum(2);
const p3 = getNum(3);
const n1 = await p1;
const n2 = await p2;
const n3 = await p3;
console.log(n1, n2, n3);
}
まとめ
async
は関数宣言で使うキーワード- async関数は戻り値にかかわらず
Promise
を返す await
はasync関数内で使うキーワードawait
はPromise
の解決を待機して値を取得する
以上。
コメントを書く