はじめに
awaitの理解がしっかりできていなかったので非同期処理の復習も込めてアウトプット
※個人ブログから技術的アウトプットはQiitaへ引っ越ししたので、こちらは過去に書いたブログとなります。
JavaSciptの非同期処理について
- JavaSctiptはシングルスレッド。
- 同時に扱えるタスクは1個だけ。
- プログラムを順番に前から1個ずつ処理する(下記のように)
しかし、これでは時間のかかる処理が途中にあった場合に困る。
例えば
- データベースへの問い合わせ(FirebaseならFirestoreのドキュメント取得等)
- 重たい画像処理
などは、完了にどれくらい時間がかかるかわからないものもある。
順番に1個づつ処理している途中で、急に処理が止まってしまい、それより後はいつ再開されるかわからない。
そこで、『非同期』が出てくる。時間のかかる処理は一旦飛ばして(後回し)、
すぐ完了できる他の処理から実行していける。それが非同期処理の特徴。
Promise について
「時間のかかる処理は一旦飛ばして」と書いたが、ちゃんとその処理が戻ってきてくれるのか不安です。
そこで登場するのが「Promise」。
例えば、「Firestoreのドキュメント取得してるから待っててね」と約束しているのです。
「まじごめん、処理重いけど、終わるまで待ってほしい、すまんな」
という**「約束」というより「お願い」**と考えた方が個人的にわかりやい!
Promiseが処理されるタイミング
非同期処理を使うときは実行されるタイミングかが大事。
function hoge (){
console.log('①おはよう')
Promise.resolve('②こんにちは')
.then(result => console.log(result));
console.log('③こんばんは');
}
function fuge () {
console.log('④深夜')
}
hoge();
fuge();
> "①おはよう"
> "③こんばんは"
> "④深夜"
> "②こんにちは"
Promiseがあるのは2番目なのに、処理は最後なる。
一体Promiseのログが一番最後になるのか?
ここは別途記載するが、コールスタック、キュー、イベントループという3つの概念が影響しているため。
async / await について
「書いた順番通りに実行してほしい!」
これを叶えるのがasync / await。
以下のようにasync と awaitを書き足すだけで、順番通り出力される。
async function hoge (){
console.log('①おはよう')
await Promise.resolve('②こんにちは').then(result => console.log(result));
console.log('③こんばんは');
}
async function hoge () {
await console.log('④深夜')
}
hoge();
fuge();
> "①おはよう"
> "④深夜"
> "②こんにちは"
> "③こんばんは"
awaitはasync関数を一時停止する
- awaitは、その時点でプログラムの実行を一旦止める
- Promiseが解決されたら次に進むようにするキーワードの役割
- つまり、Promiseが解決されるのを待っていてくれる
- awaitの後に記述された処理は、Promiseが解決されるまで実行されない
したがって、上から順に処理を実行することができる。
実務で間違ったポイント
async function hoge : Promise<boolean> {
const test = await ~~
}
async function main(): Promise<Ok> {
hoge().then(result => {
if ( !result ) {
throw new functions.https.HttpsError('internal', 'Error Message',);
}
(*中略*)
await function fuga ().then(()=>{
return ~~~~
});
業務では、上記のような感じで書いてて
hoge().then(
result => {~~
の中のエラー処理が上手く動かないな〜と悩んだ。
結果的には、
await hoge().then(
result => { ~~
をつけて中の処理が走るようになった。
普通だったらVscodeで「asyncあるのにawaitないで?」と
忠告がでますが、上記の(中略) 以下でawaitが使われていたので出なかった。。
これからは、Promiseでラップされてる関数を呼び出すときは、エラーが出てる関係なく、しっかりawaitで待ってあげるなど意識をしてあげることが大事と学んだ**。**
まとめ
- Promiseは、時間のかかる処理は一旦飛ばす
- Promiseは「まじごめん、処理重いけど、終わるまで待ってほしい、すまんな」という「約束」というより「お願い」
- 処理を飛ばさずに、書いた順番通りに実行してほしいのがasync / await
- awaitは、その時点でプログラムの実行を一旦止め、Promiseが解決されたら次に進むようにするキーワードの役割
- Promiseでラップされてる関数を呼び出すときは、エラーが出てる関係なく、awaitで待ってあげるなどの意識をしてあげることが大事