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를 만나면 어떻게 동작하는지 알아보았다!