항해의 여정(17)

qoqo_mi·2022년 6월 3일
0

항해99

목록 보기
16/23

WIL

자바스크립트의 동작원리 : Event Loop

  • 아래와 같은 방식으로 동작된다고 하면 콘솔에 찍으면 어떻게 될까 ?
const first =()=>console.log("첫번째")
const second=()=>setTimeout(()=>console.log("두번째"),500)
const third=()=>console.log("세번째")

first()
second()
third()

//출력결과 
"첫번째"
"세번째"
"두번째"
  1. Second()를 호출한다→SetTimeout 함수를 return한다.
  2. SetTimeout()의 콜백은 Web API에 추가되고 , setTimeout()과 second()이 call Stack에서 빠져나온다.
  3. 타이머가 돌아가기 시작하고 , 그 동안 first()가 호출되고 “첫번째”가 콘솔에 찍힌다.
  4. First()는 undefined를 return하고 third()가 호출되고 , 콜백이 queue에 추가된다.
  5. Third()가 로그에”세번째”라고 찍는다. Third()가 return하고 eventloop는 call stack이 빈 것을 확인하고 call stack으로 달려간다.
  6. 콜백이 “두번째”로그를 찍는다.

자바스크립트는 단일 쓰레드이지만 여러 일을 처리하는 능력이 있는 이유

브라우저에는 자바스크립트 엔진 자체가 제공하는 몇 가지 기능을 제공하는데 바로 “Web API”이다

Web API에는 DOM API , setTimeout,HTTP request 등 포함되어 있다. 이것들이 바로 우리가 async한(막히지 않는) 개발을 할 수있게 도와준다.

Call stack이 뭘까

우리가 한 함수를 호출하게 되면 그것은 call stack이라는 곳에 추가된다. Call stack은 자바스크립트 엔진의 일부분으로 명확히 따지면 브라우저가 아니다.

그냥 하나의 스택인데 ‘선입후출’ 시스템으로 실행된다. 따라서 우리가 호출한 함수가 값을 리턴하면, 그 함수는 스택에서 빠져 나온다.

function good(){
	return "Hi"
}

function smell(){
	return setTimeout(()=>{
		return "Bad"
},1000)
}

여기서 setTimeout()은 Web API가 제공하고, 메인 스레드를 막지않고 일을 수행하도록 도와준다.

그 다음 , setTimeout의 콜백함수인 {return “Bad”}는 Web API에 추가된다. 그러고 smell()과 setTimeout()은 스택에서 빠져나오고 값을 리턴한다.

setTimeout()은 Web API에서 1000ms 동안 돌아간다. 이러고나서 call stack으로 바로 가지 않고 queue공간으로 간다. (Call stack과 연관이 전혀 없는 제 3자의 공간이라 생각하면 된다. )

💡 근데 여기서 1000ms 이후에 call stack으로 추가되는 것이 아니다.

💡 그건 1000ms 이후에 단순히 queue에 넣어지는 것이고 , 해당 함수는 자신의 차례가 올 때까지 기다려야 한다.

이벤트 루프가 돌아간다

위에 과정이 이루어지면 event loop가 나온다. Event loop는 만약에 call stack이 비어지면(=다른 함수들이 return되면 ) call stack과 queue를 이어준다. 그러고 queue에 있던 첫번째 항목이 call stack에 추가된다.

이 때 다른 함수들은 호출되지 않는데 queue에서 첫번째 항목일 때 call stack이 비어졌다는 뜻이다.

💡 콜백함수가 call stack에 추가되고 → 호출한다면→ 값을 리턴→ 스택에서 빠져나옴


사실 Event Loop에는 2가지 queue가 존재한다 : macro task queue , micro queue

콜백을 받는 Promise 생성자를 통해 promise를 생성할 수 있다.

다 비동기 처리이며 우선순위로 따지면

💡 call stack에 즉시 추가되는 함수 > Promise call back함수> SetTimeout

이렇게 작동된다.

console.log("첫번째")

setTimeout(()=>{
console.log("timeout")})

Promise.resolve("Promise")
.then(res=>console.log(res))

console.log("마지막")

//출력결과 
"첫번째"
"마지막"
"Promise"
"timeout"

위와 마찬가지로 Promise는 Micro Task Queue 에 setTimeout은 macroTask Queue에 추가된다

0개의 댓글