Event Loop [JavaScript]

SnowCat·2022년 12월 28일
0
post-thumbnail

Intro

const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

wait(0).then(() => console.log(4)); //0을 설정해도 약간의 딜레이 발생
Promise.resolve()
  .then(() => console.log(2))
  .then(() => console.log(3));
console.log(1); // 1, 2, 3, 4
  • Promise에 대해 정리했을 때 MDN에서 다음과 같은 코드를 가져와 예시를 든 적이 있다. setTimeout의 경우 실행시 약간의 딜레이가 발생하고, promise가 딜레이보다 먼저 끝나는 것이 분명했기 때문에 주어진 코드에서 누가 먼저 실행될지에 대한 고민을 하지 않았어도 되었다.
  • 만약에 코드를 다음과 같이 바꾸면 되면 어떤 결과가 나올까?
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

wait(0).then(() => console.log(4)); //4가 먼저 출력될거 같다.
Promise.resolve()
  .then(() => {
  for (let i = 0; i < 10000; i++) {
    console.log(2);
    }
})
  .then(() => console.log(3));
console.log(1); // 하지만 결과는 1, 2(10000개), 3, 4
  • 크롬 콘솔에 다음 코드를 복사해 실행시키면 느긋하게 10000번의 2 출력이 끝나고 나서야 3, 4를 출력한다.
  • 예문의 결과를 이해하기 위해서는 이벤트 루프와 태스크 큐에 대한 이해가 필요하다.

자바스크립트와 호출스택

  • 자바스크립트 엔진 자체는 단일 호출 스택을 사용
var a = 1;
function outer() {
    function inner() {
        console.log('inner function:: ', a);
        var a = 3;
    }
    inner();
    console.log('outer function:: ',a);
}
outer();
console.log('outer::', a);

  • 코드에서의 각 함수들은 context에 따라 하나의 호출 스택 내부에 쌓임
  • 하나의 context가 활성화되면 다른 context는 중단되며, 자신보다 나중에 들어온 함수들의 실행이 종료되고 스텍에서 제거되기 전까지 실행될 수 없음

태스크 큐와 이벤트 루프

const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

wait(0).then(() => console.log());
console.log(1);
  • 다음 코드의 구체적인 작동 원리를 알기 위해서 태스크 큐와 이벤트 루프에 대한 이해가 필요하다
  • 태스크 큐 -> 콜백으로 호출된 함수들이 실행을 대기하는 큐 자료구조
  • 이벤트 루프 -> 태스크 큐에 있는 콜백 함수들을 호출 스택으로 옮겨 실행하는 역할, 현재 실행중인 태스크가 없을 때(보통 호출 스택이 비어있을 때)마다 이벤트 루프를 통해 태스크 큐의 함수들을 옮김

Promise와 마이크로 태스크 큐

const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

wait(0).then(() => console.log(4));
Promise.resolve()
  .then(() => {
  for (let i = 0; i < 10000; i++) {
    console.log(2);
    }
})
  .then(() => console.log(3));
console.log(1);
  • 다시 처음의 코드로 돌아가보자, Promise는 태스크 큐에 있는 콜백함수보다 우선 실행되는것은 분명하다. 이유는 마이크로 태스크(Micro Task) 큐에 있다.
  • 마이크로 태스크 큐 -> 일반 태스크 큐보다 우선순위를 갖는 이벤트 큐
  • 코드에서 2, 3을 출력하는 promise는 마이크로 태스크 큐에 들어가고, setTimeout을 통해 4를 출력하는 함수는 태스크 큐에 들어가게 됨
  • 결과적으로 마이크로 태스크 큐가 우선 실행됨으로 2, 3이 4보다 우선 출력됨

https://meetup.nhncloud.com/posts/89
https://velog.io/@seonghyeon01/javaScript-%EC%8B%A4%ED%96%89%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8%EC%99%80-%EC%BD%9C-%EC%8A%A4%ED%83%9D

profile
냐아아아아아아아아앙

0개의 댓글