おはようございます。
今日からモーニングルーティンをアップデートしてしっかり朝活取り組んでおりますどうもハヤトワンです。
さて、非同期処理のマイクロタスクとマクロタスクについて、昨日の補足をしていきます。
▼マイクロタスク
順番が回ってきたら全てのジョブを実行する。
▼マクロタスク
順番が回ってきたら1つずつタスクを実行
例:
コールスタック:context
マイクロタスク(ジョブキュー):ジョブ1、ジョブ2
マクロタスク(タスクキュー):タスク1、タスク2
があったとする。
そして、まずコールスタックがなくなると、
マイクロタスクのジョブが全て終了してから、マクロタスクの中のタスクが1つだけ実行される
コールスタック:context
↓
マイクロタスク(ジョブキュー):ジョブ1、ジョブ2
↓
マクロタスク(タスクキュー):タスク1、タスク2
そしてこの間に、マイクロタスクの中にさらにジョブ3、ジョブ4の2つが追加された場合、
マイクロタスクのジョブを2つ実行してから、マクロタスクに格納されているタスク2が実行されることになる。
コールスタック:
↓
マイクロタスク(ジョブキュー):ジョブ3、ジョブ4
↓
マクロタスク(タスクキュー):タスク2
これがマイクロタスクとマクロタスクの挙動の違い。
この場合はどうなるか
new Promise(function promise(resolve) {
console.log('promise');
setTimeout(function task1() {
console.log('タスク1');
resolve();
});
}).then(function job1(){
console.log('ジョブ1')
});
console.log('global end');
コンソール
promise
global end
タスク1
ジョブ1
になる。
まず最初に同期的に実行されるPromiseのconsole.log
これ以外はsetTimeoutやthenの中は非同期処理になるので、次に出力されるのはconsole.log(‘global end’)になる。
今回の場合、setTimeoutの中にresolveがあるため、resolveの実行を待つthenメソッドのコールバック関数は一番最後に実行されることになる。
登場人物
・コールスタック
・非同期API
・マイクロタスク(ジョブキュー)
・マクロタスク(タスクキュー)
まずスクリプトが実行されると、グローバルコンテキストからNew Promiseの中のコールバック関数のPromiseが実行される
このPromiseの中でsetTimeoutが呼ばれ、このsetTimeoutのコールバック関数の中でresolve()が呼ばれる。、そしてPromiseのthenメソッドのコールバック関数であるジョブ1がresolveを待つ待機状態になる。(非同期APIの中)
次にsetTimeoutのコールバック関数である、タスク1がマイクロタスクに格納される。
そしてコールスタックがはけていくと、(promise、グローバルがなくなる)このときにはマイクロタスク(ジョブキュー)にはなにも格納されていないので、マクロタスク(タスクキュー)のタスク1がコールスタックに移動することになる。
このタスク1の中にはresolve()を保持しているので、このresolveが実行されたときにthenメソッドが呼ばれ、マイクロタスクにジョブ1が登録される。
そしてコールスタックがもう一度はけると(タスク1とresolveがなくなる)、次はジョブ1がコールスタックに上がってくるため、一番最後にジョブ1が上がってくる。
setTimeoutの中でresolveが呼ばれた場合はこのようなイメージを持つといい。
ふむふむ。
順番がしっかりあるんですね〜。
てことで続きはまた明日。
今日もいい1日を!