前回はPromiseについて書きましたが、その続きで今回はasync/awaitについて。
【参考】
async/await 入門(JavaScript)
asyncとは
非同期関数を定義する関数宣言のこと。
async関数は、以下の動作をする。
- Promiseを返す
- 値をreturnすると、Promiseはそれをresolveする。
- エラーなどをスローすると、Promiseはそれをrejectする。
- 関数内部でawaitを使用できる。
// 普通こんな書き方しませんが、サンプルということで。 function main() { const even = checkEven(2); // この場合、コンソールには「偶数です」と表示される。 even.then((message) => { console.log(message); }).catch((err) => { console.log(err.message); }); const odd = checkEven(1); // この場合、コンソールには「奇数です!」と表示される。 odd.then((message) => { console.log('偶数です'); }).catch((err) => { console.log(err.message); }); } async function checkEven(num) { if(num % 2 === 0) { // resolve('偶数です')と同じ。 return '偶数です'; } else { // reject('奇数です!')と同じ。 throw new Error('奇数です!'); } }
awaitとは
- Promiseを返す関数について、Promiseの結果(resolveやreject)が返されるまで、処理を待つ。
- 同期処理みたいな動作になる。
- awaitを付けた場合、戻り値に格納されるのはresolve、あるいはrejectされた値となる。
- rejectされたのがエラー場合、そのエラーが発生する。(catch()処理などを実施する必要あり)
- async関数内でのみ使用できる。
先程の関数を、awaitを使って書くと、こうなります。
async function main() { // この場合、messageにはresolve値の「偶数です」が格納されるので、 // それがそのまま表示される。 try { const even = await checkEven(2); console.log(even); } catch(err) { console.log(err.message); } // この場合、checkEvenからErrorがスローされるので、コンソールには // err.message(「奇数です!」)が表示される。 try { const odd = await checkEven(1); console.log(odd); } catch(err) { console.log(err.message); } } async function checkEven(num) { if(num % 2 === 0) { // resolve('偶数です')と同じ。 return '偶数です'; } else { // reject('奇数です!')と同じ。 throw new Error('奇数です!'); } }
await使用時の注意点
- awaitは基本的に「resolveの値がないと、それ以降の処理ができない」際に使用する。(下記など)
- ファイルの内容を取得する
- DBのあるテーブルのレコードを取得する
- awaitは先述の通り「Promiseの結果が返されるまで、処理を待つ」動作。
- async関数だからと言って、なんでもawaitすればいいわけではない。
- 使い方を間違えると、レスポンス時間の遅延につながる。(下記ソース)
async function main() { // funcVal1~funcVal3が「それぞれ処理に5秒かかる」場合、 // awaitで直列処理してしまうと、main()が終わるのに15秒かかってしまう。 try { const val1 = await funcVal1(); const val2 = await funcVal2(); const val3 = await funcVal3(); } catch(err) { } // この場合、await は使わず、Promise.all()を使って並列処理すれば // main()が終わるのは5秒で済む。 const func1 = funcVal1(); const func2 = funcVal2(); const func3 = funcVal3(); Promise.all([func1, func2, func3]).then(([val1, val2, val3]) => { // すべて正常終了した際の処理 }).catch((err) => { // どれか一つでもErrorがスローされた際の処理 }); }
また急ぎ足気味になってしまいましたが、今日はこの辺で。