🌟

イベントループとタスクキューを理解する

2024/03/05に公開

目的

イベントループ、タスクの理解が曖昧なので整理したい。

ログを見ながら確認

まずは初歩的なところから

下記のコードは、どの順番でログ出力されるのかを考える。

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. まずは1行目のPromise.resolve()が呼び出され、コールスタックに格納される。これはすぐに解決されるプロミスであるため、.then()がすぐにスタックにプッシュされ、マイクロタスク キューにコールバック関数の() => console.log(1)がスケジューリングされる。
    1

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

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

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

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

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

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

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

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

終わりに

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

参考資料

GitHubで編集を提案

Discussion