JavaScriptでは、通常は非同期処理となり、重い関数が終わるまで待つということをせず、次の関数に先に制御が移ってしまいます。
そのため、API呼び出しやIO(ファイルの読み書きやDBの読み書き)を伴う関数を呼び出した後に、その結果を元に次の処理を行う、というフローを行うためには一工夫必要です。
これを簡単に書くために、JavaScriptにはasync/awaitという文法が用意されています。
この記事では、非同期処理のサンプルコードと、async/awaitを用いて同期処理にするサンプルコードを用意しているので、そのサンプルコードを読めば使い方は理解できると思います。
async/awaitを使う上での注意点として、promiseやresolveとセットで使う必要があるという点があります。
これをセットで使用しないと、同期処理にならない、待った後の処理が実行できない、等のバグになります。
async/awaitはpromiseオブジェクトを簡単に扱うための文法でもあるので、promiseについては別途Webで調べるとより理解が深まると思います。
【サンプルコード(非同期処理)】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// すぐ終わる処理 function lightTask() { console.log("light"); } // 1秒かかる重い処理 function heavyTask() { const procedure = () => { console.log("heavy"); } setTimeout(procedure, 1000); } // JavaScriptは通常は非同期なので、heavyTaskの終了を待ってくれない function exection() { heavyTask(); lightTask(); } exection(); |
【処理結果(非同期処理)】
1 2 3 4 5 |
C:\tmp>node sample.js light heavy C:\tmp> |
【サンプルコード(同期処理)】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
function lightTask() { console.log("light"); } function heavyTask() { // awaitで呼び出される関数ではpromiseオブジェクトを返す必要がある return new Promise((resolve, reject) => { const procedure = () => { console.log("heavy"); resolve(0); // returnではなくresolveで戻す(これを忘れると制御が戻らない) } setTimeout(procedure, 1000); }); } // awaitを使用する関数にはasyncをつける async function exection() { let result = await heavyTask(); // awaitで呼び出すことで処理が終わるまで待つ // console.log(result); // 0 lightTask(); } exection(); |
【処理結果(同期処理)】
1 2 3 4 5 |
C:\tmp>node sample.js heavy light C:\tmp> |
いかがでしたでしょうか。
JavaScriptのフレームワークを使いこなすには、まずJavaScript自体のことについて知る必要があります。
JavaScriptでは意識してコードを書かないと非同期処理になってしまうので、ここは意外と落とし穴になるのではないかと思っています。
コメント