alt
Home Event loop, 비동기 처리의 흐름
Post
Cancel

Event loop, 비동기 처리의 흐름


Javascript

  • 싱글스레드 기반, Event loop를 기반으로 하는 Node.js
  • Javascript engine은 JS를 해석하고 실행하는 엔진(콜 스택과 이벤트 큐가 있는)


Javascript engine과 이벤트 루프

Event Loop

  • 아래의 방식으로 이벤트루프가 현재 실행중인 task가 없는지, task queue에 task가 있는지 반복적으로 확인
1
2
3
while(queue.waitForMessage()) {
	queue.processNextMessage();
}


Call stack

  • JS는 단 하나의 call stack 사용
    • 자바스크립트 엔진의 call stack
  • 따라서 JS가 실행되는 방식은 Run to completion. 하나의 함수가 실행되면 다른 task는 수행될 수 없다.
  • 메서드 실행시 call stack에 새로운 stack frame 생성하고 return시 stack에서 해당 frame을 pop한다.
    • 혹은 비동기적인 처리가 필요할 때 pop되고 Web API로


Heap

: 동적으로 생성된 객체(인스턴스)는 힙에 할당.


Microtask queue

  • task queue보다 여기를 우선적으로 확인
  • mutation observer(?), promise가 여기로 들어감.
  • Promise의 핸들러는 항상 이 queue를 통과해야 한다.
    • 처리되지 못한 에러: microtask queue가 빈 후 처리하지 못한 error에 대해 unhandledrejection 발생.


Task Queue(event queue)

  • JS 런타임환경에는 (비동기적으로)처리해야하는 Task를 임시저장하는 대기 큐가 존재. 그것이 Task queue( == event queue.)
  • Call stack이 비어졌을 때 queue에 먼저 들어온 task가 stack으로 들어간다.
  • 비동기로 호출되는 함수는 (Web API에서 수행된 후)Task queue에 enqueue된다.
  • 여기서 지워지는 타이밍은 stack에서 수행 후 pop 되고 나서.

web API or 백그라운드

  • 자바스크립트의 엔진(실제 코드가 수행되는 쓰레드)와는 별도의 쓰레드
  • Ajax 요청, setTimeout(), 이벤트 리스너 등록 과 같은 것들이 이 곳에서 수행
    • Settimeout에서 n초가 다 수행되기 전까지, event handler에서 해당 event가 발생하기 전까지 기다리는 곳
  • 이후 발생하거나 완료 되면 task queue(자바스크립트 엔진의 쓰레드)로 보낸다.


queue 우선순위

  • micrortask queue -> animation frames -> task queue
  • 직접적인 작업들은 Web API에서 처리한다.
  • animation frame : 브라우저 랜더링 관련


c. f) 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function aaa() {
  setTimeout(() => {
    console.log('d');
  }, 0); 
  console.log('c');
}

setTimeout(() => {
  console.log('a');
  aaa();
}, 0);

Promise.resolve().then(() => {
  aaa();
  console.log('b');
});
  • 출력순서 예상해보기. 답 c b a c d d


Async / Await, microtask

  • await을 만나면 해당 async 함수 실행이 일시정지되고 async 컨택스트 전체가 microtask queue로 삽입된다. 이 후, await 된 함수가 resolve된 promise를 리턴할 때 까지 지연된다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    const hello = () => Promise.resolve('Hello world');
      
    async function myFunc() {
        console.log('In function!');
        const rest = await hello();
        console.log(res);
    }
    console.log('Before');
    myFunc();
    console.log('After');
    
    • 결과는 Before -> In function -> After -> One



#### Reference)

https://it-eldorado.tistory.com/86

http://asfirstalways.tistory.com/362

https://it-eldorado.tistory.com/86

http://sculove.github.io/blog/2018/01/18/javascriptflow/

https://kkangdda.tistory.com/77

This post is licensed under CC BY 4.0 by the author.