bkdragon's log

JavaScript 엔진이 await를 만났을 때 본문

concept

JavaScript 엔진이 await를 만났을 때

bkdragon 2023. 7. 18. 22:16

async 함수에서 await 키워드를 만나면 await가 붙은 함수를 일단 실행 시킨다. 이 함수는 Promise를 반환하는 비동기 함수 일 것이다. 해당 함수의 프로미스가 이행되면 await의 위치에서 async 함수의 동작을 중지하고 마이크로 태스크 큐로 이동한다. 콜 스택에 남은 동작을 실행한다.(없을 수 있다.) 콜 스택이 비면 이벤트 루프에 의해 마이크로 태스크 큐의 async 함수가 멈춘 지점을 기억한 채로 돌아온 다음 await 이후로 다시 실행 된다.

 

코드를 보며 동작을 확인 해보자.

async function f() {
  console.log(1);
  let promise = new Promise((resolve, reject) => {
    console.log(1.5);
    setTimeout(() => resolve('완료!'), 1000);
    console.log(1.4);
  });
  let result = await promise;
  console.log(2);
  console.log(result);
}

console.log(5);
f();
console.log(6);

이 코드는 아래와 같이 출력 될 것이다.

5, 1, 1.5, 1.4, 6, 2, 완료!

await promise 에서 resolve 이후 f 함수는 실행을 중지하고 마이크로 태스크 큐로 이동한다. 그래서 다음 동작이 같은 컨텍스트에 있는 console.log(6)이다. 그 이후엔 호출 스택이 비어서 f가 다시 복귀하는 것이다.

 

조금 더 복잡한 예시를 보자.

const delayTimeOut = async (text, time) => {
  setTimeout(() => {
    console.log('timeout' + text);
  }, time);
};


const delayPromise = async (text) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('Promise' + text);
      resolve(); // 성공
    }, 0);
  });
};

const a = async () => {
  console.log(1);
  await delayTimeOut('first', 0);
  console.log(2);
  await delayPromise('first'); 
  console.log(3);
};

a();

 

이 코드는 아래와 출력 된다.

1,
2,
timeout first,
Promise first,
3

Promise callback에 setTimeout이 있어서 이렇게 동작한다 앞서 실행된 delayTimeOut 함수의 setTimeoutd이 먼저 매크로 태스크 큐에 들어가 있다. 만약 시간이 늘어나면? 콜 스택이 완전히 비었을 때 timeout first가 출력될 것이다.

 

 const a = async () => {
  console.log(1);
  await delayTimeOut('first', 1000);
  console.log(2);
  await delayPromise('first'); 
  console.log(3);
};

a();

 

delayTimeOut에 1000,

 

1,
2,
Promise first,
3,
timeout first

 

 

JavaScript 엔진 await를 만나면 어떻게 동작하는지 알아보았다!

'concept' 카테고리의 다른 글

[Redux] Redux Toolkit  (0) 2023.07.27
[Cookie] 내가 만든 Cookie  (0) 2023.07.26
Flux 패턴  (0) 2023.07.17
[TEST] MSW와 통합 테스트  (0) 2023.07.12
[TEST] 프론트의 단위 테스트와 BDD  (0) 2023.07.09