내용 보기

작성자

관리자 (IP : 172.17.0.1)

날짜

2020-09-08 07:34

제목

[TypeScript] 자바스크립트의 이벤트 루프 설명


각각 1밀리초와 2밀리초 후에 실행되는 두개의 타이머를 설정했다.

setTimeout(() => console.info('A'), 1);
setTimeout(() => console.info('B'), 2);
console.lnfo('C');
cs

콘솔에 결과는 A, B, C가 아니라 C, A, B가 출력된다.

자바스크립트의 동시성 모델은 다음과 같은 구조로 되어 있다.


[그림 : 자바스크립트의 이벤트 루프 : 비동기  API를 호출할 때 일어나는 일]


● 메인 자바스크립트 스레드는 XMLHttpRequest(AJAX 요청), setTimeout(타이머), readFile(디스크 파일 읽기) 등의 네이티브 비동기 API를 호출한다.
이들  API는 자바스크립트 플랫폼에서 제공하며 직접 만들 수 없다.
(브라우저 플랫폼을 포크(pork)하거나 C++용 NodeJS확장을 이용하면 직접 만들 수 있다.)

 네이티브 비동기 API를 호출한 이후다시 메인 스레드로 제어가 반환되며 아무 일도 없었던 것 처럼 코드를 계속 실행한다.

비동기 작업이 완료되면 플랫폼은 태스크(task)를 이벤트 큐에 추가한다.
각 스레드가 자신만의 큐를 가지고 있으며 이를 이용해 비동기 연산 결과를 메인 스레드로 전달한다.
태스크에는 호출 자체와 관련해 메타 정보 일부와 메인 스레드와 연결된 콜백 함수의 참조가 들어 있다.

메인 스레드의 콜 스택이 비면 플랫폼은 이벤트 큐에 남아 있는 태스크가 있는지 확인한다.
대기 중인 태스크가 있으면 플랫폼은 그 태스크를 실행한다.
이때 함수 호출이 일어나며 제어는 메인 스레드 함수로 반환된다.
함수 호출이 끝나고 콜 스택이 다시 비면 플랫폼은 다시 기다리는 태스크가 있는지 이벤트 큐에서 확인한다.
콜 스택과 이벤트 큐가 모두 비고, 모든 비동기 네이티브 API 호출이 완료될 때까지 이 과정을 반복한다.


이 순서를 기억하고 위 setTimeout코드에 대해 순서를 보면

1. setTimeout을 호출하면 우리가 건넨 콜백 참조와 1을 인수로 네이티브 타임아웃 API를 호출한다.

2. setTimeout을 다시 호출하면 두 번째 콜백 참조와 2를 인수로 네이티브 타임아웃 API를 다시 호출한다.

3. C를 콘솔에 출력한다.

4. 백그라운드에서 1밀리초가 지난 다음 자바스크립트 플랫폼이 태스크를 이벤트 큐에 추가하여, 첫 번째 setTimeout에서 지정한 시간이 만료되었고 콜백을 호출할 수 있음을 알린다.

5. 다시 1밀리초가 지난 다음 플랫폼이 두 번째  setTimeout의 콜백을 호출할 수 있도록 두 번째 태스크를 이벤트 큐에 추가한다.

6. 콜 스택이 비었으므로 3번 과정을 완료한 플랫폼은 이벤트 큐에 태스크가 있는지 확인한다.
4, 5번 과정 중 하나라도 완료되었다면 태스크가 존재할 것 이다.
발견한 각 태스크에서 관련 콜백 함수를 호출한다.

7. 설정한 두 타임아웃이 모두 지났고 이벤트 큐와 콜 스택이 모두 비었다면 프로그램이 종료된다.

이런 방식으로 A, B, C가 아니라 C, A, B가 출력된다.

출처1

출처2