イベントループとタスクキューを理解する
目的
イベントループ、タスクの理解が曖昧なので整理したい。
ログを見ながら確認
まずは初歩的なところから
下記のコードは、どの順番でログ出力されるのかを考える。
Promise.resolve().then(() => console.log(1));
queueMicrotask(() => console.log(2));
setTimeout(() => console.log(3), 0);
console.log(4);
new Promise(() => console.log(5));
async () => console.log(6);
正解は
4, 5, 6, 1, 2, 3
実行手順を見ていく
図はcanvaで書きました。
-
まずは1行目の
Promise.resolve()が呼び出され、コールスタックに格納される。これはすぐに解決されるプロミスであるため、.then()がすぐにスタックにプッシュされ、マイクロタスク キューにコールバック関数の() => console.log(1)がスケジューリングされる。

-
次に
queueMicrotask()を呼び出し、コールスタックに格納される。これによりマイクロタスク キューにコールバック関数の() => console.log(2)がスケジューリングされる。

-
次に
setTimeout()がコールスタックに格納され、そのコールバックがWeb APIにスケジューリングされる。

-
setTimeout()コールバック関数の() => console.log(3)がマクロタスク キューにスケジューリングされると同時に、console.log(4)がコールスタックにプッシュされる。これは単なる通常の関数なので、4がまず最初に出力される。

-
次の
new Promise()コンストラクタでは、() => console.log(5)は同期的に実行される。あくまでも結果部分(thenなど)を非同期で実行するため。したがって、console.log(5)がコールスタックにプッシュされ、2番目に出力されるのは5となる。

-
次に、
async () => console.log(6)が呼び出されるが、() => console.log(6)は同期的に実行される。あくまでも非同期で実行される部分はawaitから始まっているものであるため。したがってconsole.log(6)がコールスタックにプッシュされ、3番目に出力されるのは6となる。

-
コールスタックが空になったので、マイクロタスク キューの最初のタスクがコールスタックに追加される。したがって
console.log(1)がコールスタックにプッシュされ、4番目に出力されるのは1となる。

-
同様に、
console.log(2)がコールスタックにプッシュされ、5番目に出力されるのは2となる。

-
最後に、マクロタスク キューがコールスタックに追加される。したがって
console.log(3)がコールスタックにプッシュされ、最後に出力されるのは3となる。

終わりに
図を用いることで、自分なりに整理できた。
少し長くなったので、今回はここまでに🙇♂️
Discussion