async/awaitの使用および注意事項
6629 ワード
async / await
を用いる、promise
と組み合わせることで、同期のようなコードを記述することによって非同期の流れを処理することができ、コードの簡潔性と可読性を高めることができる.本文はasync / await
の基本的な用法といくつかの注意事項を紹介する.await
MDNの説明を参照:
await
オペレータは、非同期関数Promise
の内部でのみ使用できるasync function
オブジェクトを待つために使用される.await
の使用文法は非常に簡単です.[return_value] = await expression;
expression
は、Promise
オブジェクトまたは待機する任意の値である.await expression
の実行結果には、次のような状況があります.expression
がPromiseオブジェクトである、その値x
がfulfilledである場合、戻り値はx
である.expression
がPromiseオブジェクトである、異常e
でrejectedされると、異常e
が投げ出す.expression
がPromiseオブジェクトでない場合、expression
は、expression
の値をfulfilledとするPromiseオブジェクトに処理され、そのPromiseオブジェクトの最終値(すなわちexpression
の値)に戻る.このような用法はあまり意味がないので、実際に使用する場合はawait
の後にPromiseの対象となるようにする.なお、
await
は、Promiseオブジェクトを待つ間にasync function
の実行を一時停止する、Promiseオブジェクト決議の後になってからasync function
の実行を継続する.コードを見てみましょう.
async function foo() {
var a = await new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, 2000);
});
console.log(a); // 2 : 1
try {
var b = await new Promise((resolve, reject) => {
setTimeout(() => {
reject(2);
}, 1000);
})
} catch (e) {
console.log(e); // 3 : 2
}
// 2
var sleep = await new Promise((resolve) => {
setTimeout(() => {
resolve('sleep');
}, 2000);
});
var c = await 3;
console.log(c); // 5 : 3
}
foo();
async
async function
を使用して、非同期関数を定義します.構文は次のとおりです.async function name([param[, param[, ... param]]]) { statements }
async
の関数の戻り値は特殊である:関数体内のreturn
がどんな値であるかにかかわらず、async
の関数の実際の戻り値は常にPromise
の対象である.詳しくは、async
の関数のうちreturn
に1つの値x
があると、x
の値がどのような種類であるかにかかわらず、async
の関数の実際の戻り値は常にPromise.resolve(x)
である.では、
Promise.resolve(x)
は最終的にどのようなpromiseを返しますか?MDNの紹介を見てみましょう.Promise.resolve(value)メソッドは、所与の値で解析されたPromiseオブジェクトを返します.しかし、この値がthenable(すなわちthenメソッド付き)である場合、返されるpromiseはこのthenableのオブジェクトを「フォロー」し、その最終状態(resolved/rejected/pending/settledを指す)を採用する.そうでなければ、この値を成功状態としてpromiseオブジェクトを返します.
次にコードの応用を見ます.まず、要求1によりデータ1を取得する、その後、要求2により送信データ1を携帯することによりデータ2を取得し、データ2を取得してからページに表示するシーンがあるとする.
シナリオ1:
async function showData() {
// 1
var data1 = await new Promise((resolve) => {
setTimeout(() => {
resolve('data1');
}, 1000);
});
// 2 1
var data2 = await new Promise((resolve) => {
setTimeout(() => {
resolve('data2');
}, 1000);
});
// 2
console.log(data2);
}
showData();
上記のコードは、データ1とデータ2を順次取得する、データ2を示す.
async
関数が常に1つのpromiseを返す以上、1つのasync
関数でデータ2を取得するpromiseを返し、関数を呼び出した後、then
方法でデータを取得することもできます.コードは以下の通りです.async function getData() {
// 1
var data1 = await new Promise((resolve) => {
setTimeout(() => {
resolve('data1');
}, 1000);
});
// 2 1
return new Promise((resolve) => {
setTimeout(() => {
resolve('data2');
}, 1000);
});
}
getData().then((v) => {
console.log(v);
});