非同期処理がなかなか理解できなかったので、コードと一緒に理解できるようにする。
以下のコードを走らせるとどのような結果になるか。nodeで実行してみる。
setTimeout(() => {console.log(1)},1000)
console.log(2);
setTimeout(() => {console.log(3)},0)
console.log(4);
setTimeout(() => {console.log(5)},1000)
console.log(6);
setTimeout(() => {
console.log(7);
setTimeout(() => {
console.log(8);
},1000)
},2000)
結果
2
4
6
3
1
5
7
8
表示順は2,4,6,3
がすぐに表示され、その1秒後に1,5
が表示され、その1秒後に7
が表示され、その1秒後に8
が表示されます。
同期処理と非同期処理は、まず同期処理が優先して処理されます。その処理が終わった後に非同期処理が実行されます。console.log(1)
とconsole.log(5)
は同時に動きます。このあたり自分は1秒ずつずれて動くと勘違いしてました。
これをずらして動かすためには、 setTimeout()関数の中にsetTime()関数を入れ込む(callbackする)必要があります。7,8
でcallbackをさせています。
*top画面のイメージを参考にしてください。
上のcallbackを使って、カウントダウンするコードを書くと以下のようになります。
setTimeout(() => {
console.log(3);
setTimeout(() => {
console.log(2);
setTimeout(() => {
console.log(1);
}, 1000);
}, 1000);
}, 1000);
結果
3
2
1
これは、可読性が悪くコードの管理も難しいということでコールバック地獄とかよく呼ばれています。 こうしたコールバック地獄を避けるためにPromiseがあります。
まずはコードを書きます。結果は同じです。
new Promise((resolve) => {
setTimeout(() => {
console.log(3);
resolve();
}, 1000);
})
.then(() => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(2);
resolve();
}, 1000);
});
})
.then(() => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(1);
resolve();
}, 1000);
});
});
Promiseオブジェクトは第1引数にresolve
、第2引数にreject
を指定でき、resolve()
させるとthen
以下の関数が実行され、reject()
させるとcatch
以下の関数を実行させることができます。これにより非同期処理の可読性が高まり、またthen
やcatch
により複雑な処理も可能になりました。
上記のコードの場合、resolve()
により、then以下で独立してPromiseが動いています。
前のコードより複雑化したように思うかもしれませんが、メインテナンスはやりやすくなったのではと思います。
最後にasync/awaitを使って書き直します。
func = async () => {
// 関数に対してasyncと宣言する => この関数は非同期関数
await log(3);
await log(2);
await log(1); // 関数の呼び出しの前にawait => Promiseの結果がくるまで待つ
};
log = (num) => {
// Promiseを返す関数
return new Promise((resolve) => {
setTimeout(() => {
console.log(num);
resolve();
}, 1000);
});
};
func();
functionの前にasync
をつけると、非同期処理を実行できる関数を定義できる。
await
はasync
で定義された関数の中で使う。
log関数は、setTime()を使った待機処理関数をPromiseでラップしたもので、resolve()で結果を返す。
これをawait
の後で、実行するとPromiseでthen
を使って実行させたことをthenなし
で実行させることができるようになりました。
async/awaitは、コードはシンプルになるが、裏でPromiseが動いているので、そこを理解しないといけないなと思いました。
いろいろなコードを書きながら非同期処理の理解を深めていきたい。
https://qiita.com/cheez921/items/41b744e4e002b966391a
https://knowledge.sakura.ad.jp/24890/
https://rightcode.co.jp/blog/information-technology/javascript-async-await
小学生でもわかるasync/await/Promise入門【JavaScript講座】
可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。
Read More可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。
Read More