書いてあることはあくまで自分が理解するためのイメージです。正しくありません。
非同期処理とは
同期処理:タスクA、タスクBが順に実行される。
非同期処理:タスクAの実行を他に一度任せてタスクBから実行できる。
コールバック関数
関数に引数として渡される関数のことをコールバック関数と呼ぶ。
コールスタックとタスクキュー
- コールスタック:逐次処理(同期処理)の待合室。実行開始に伴いpush,実行終了に伴いpopが起こる。
- 実行時に非同期処理の物はタスクキューに送られる。
- タスクキュー:非同期処理の待合室。タスクキューの中のものはコールスタックが空になるとコールスタックへと返される&実行される。
setTimeout
- 非同期処理を行える。つまり中の関数をタスクキューに送れる。
- setTimeout(関数,時間)と記述し実行終了から表示まで時間を置く。
- setTimeout(タスクA);タスクB;とすることによってタスクBを先に実行できる(非同期処理)。
関数1{setTimeout(関数2,1000);関数3;} 関数4{}
だと実行順は
- 関数1がコールスタックにpush(実行開始)
- 関数1内の関数2がタスクキューに渡される。
- 関数3が実行開始&終了
- 関数1がコールスタックからpop(実行終了)
- 関数4が実行開始&終了
- 関数2がコールスタックに帰ってくる。
- 関数2が実行される。
結果:関数3→(関数1)→関数4→関数2の順で実行される。
コールバック地獄
関数4→2→3の順で実行したいとする。
関数1{setTimeout(関数2;関数3,1000)} 関数4
または1秒刻みで出力したい場合
関数1{setTimeout(関数4(setTimeout(関数2;setTimeout(関数3,1000),1000),1000)}
となるがネストが深すぎて読みずらい→コールバック地獄
promise
- setTimeoutで任せたタスクAが終わり次第実行してほしいタスクBがあったとする。上のコールバック地獄のような例でも実行可能だが、promiseを使うとスマートに書ける。
- promise内のコールバック関数には引数としてresolve,rejectが渡される
- コールバック関数はresolve()またはreject()を実行する。
- プロミスがresolve状態のとき→promise.then(関数B)
- プロミスがreject状態のとき→promise.catch(関数B)
- 関数Bの引数にはresolve(),reject()内の引数が渡される。
promise((reject,resolve) => {setTimeout(関数A,2000});resolve();)
promise.then(関数B)
- setTimeoutは非同期処理なので関数Aがタスクキューに投げられる。
- 2秒後に関数Aがコールスタックに帰ってきて実行される。
- resolveが実行される
- promiseオブジェクトはresolve状態なのでthenに処理が進む
明日はpromise.async,awaitまとめる