이벤트 루프와 스레드 블로킹

setTimeout(() => {
  console.log("1");
}, 50);

setTimeout(() => {
  console.log("2");
}, 10);

Promise.resolve().then(() => {
  console.log("4");
});

console.log("5");

for (let i = 0; i < 10000000; i++) {
  JSON.parse('{ "test": "test" }');
}

setTimeout(() => {
  console.log("6");
}, 5);

setTimeout(() => {
  console.log("7");
}, 1);

Promise.resolve().then(() => {
  console.log("9");
});

console.log("10");

호출 순서가 어떻게 될까.

t=0ms

  • 1번 타이머 등록, 50ms 이후 Macro Queue 에 적재된다.
  • 2번 타이머 등록, 10ms 이후 Macro Queue 에 적재된다.
  • 4번 등록, 바로 Micro Queue 에 적재된다.
  • 5번이 콜 스택에 적재되고 실행된다.
  • JSON.parse Loop 가 실행되며 약 800ms 가 소요된다.

t=800ms (Loop 완료, 메인 스레드 블로킹)

  • 6번 타이머 등록, 805ms에 Macro Queue 에 적재된다.
  • 7번 타이머 등록, 801ms에 Macro Queue 에 적재된다.
  • 9번 등록, 바로 Micro Queue 에 적재된다.
  • 10번이 콜 스택에 적재되고 실행된다.

t=800ms 이후 (이벤트 루프 동작)

  • Micro Queue 실행
    • 4번 실행
    • 9번 실행
  • Macro Queue 실행
    • 2번 실행 (10ms 면 Loop 동안 만료되었으므로 바로 실행)
    • 1번 실행 (50ms 면 Loop 동안 만료되었으므로 바로 실행)
    • 7번 실행 (801ms 에 만료되고 실행된다.)
    • 6번 실행 (805ms 에 만료되고 실행된다.)

결과는 5 → 10 → 4 → 9 → 2 → 1 → 7 → 6 가 된다.