初めに
自分は業務中でよくPromiseで非同期処理を実現しますが、そもそもなぜPromise使うのかをよくわからないので、今回は基礎からJavaScriptの非同期とコールバックについて整理してみます。
先ずは定義
非同期処理:JSにおける非同期処理は、プログラムコードを上から順に1行ずつ実行していきません
コールバック:他のコードの引数として渡されるサブルーチンである
例
function A(callback){
console.log("I am A");
callback(); //渡されるサブルーチン
}
function B(){
console.log("I am B");
}
A(B);
非同期処理とコールバック
コールバックは非同期処理を実現するの手段の一つであり、逆にコールバックで実装したコードは必ず非同期処理とは言えません。
上の例がコールバックで同期処理の例です。
で、次は非同期処理を見にいきましょうか。
また、以下のような関数があります
f1() // 時間をかかる
f2() // f1の次の番実行する
f3() // f1,f2と関係ない、できれば早めに実行する
f1の実行に時間がかかるのため、f2とf3は待つしかない
コールバックで非同期させます:
function f1(callback){
setTimeout(function () {
// do some thing
callback();
}, 1000);
}
f1(f2);
f3();
こういう書き方だと、setTimeoutを使ってf1を非同期処理させ、f3を早めに実行できるようになりました。
なぜ非同期なのか?
JavaScriptの特徴の一つにシングルスレッドがあります。
であれば、どうやって一つスレッドしかを使わないで非同期を実現する?
答えはEvent Loopとのことです。
(event-loopのインメージ from 「Help, I’m stuck in an event-loop」)
要するに、JavaScriptの実行順番は下記となります:
➀:heap、stackを生成する
②:stack中のコードを外部apiを呼び出し、イベント(click,load,done)をcallback queueに追加する
③:stack中のコードの実行が終わったら、callback queue内のcallback functionをstackに投げる
④:step➀に戻る
ですので、上記の例で、f1()をsetTimeout経由でcallback queueに追加し、とりあえずf3()を実行します。
要注意:setTimeoutの設定通り、1000ms後、コールバック関数を実行ではなくて、callback queueに追加するだけです。
まとめ
今回は基礎からJavaScriptの非同期とコールバックについて整理し、非同期処理の流れが明確になりました。