Promise가 아닌 비동기 함수 동작에 관하여
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const get = url => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.send();
xhr.onload = () => {
if(xhr.status === 200) {
console.log(JSON.parse(xhr.response));
} else {
console.error(`${xhr.status} ${xhr.statusText}`);
}
};
};
get('https://jsonplaceholder.typicode.com/posts/1');
</script>
</body>
</html>
get함수는 비동기함수이다. 비동기함수란 함수 내부에 비동기 동작 코드가 있는 함수이다.
비동기함수 호출시 비동기 호출이 완료되기 전에 비동기함수는 종료된다.
위 코드를 실행하면 아래처럼 콘솔로 출력을 확인할 수 있다.

내부 동작 순서를 정리해보겠다.

1. get함수가 호출되어 send하며 이벤트 핸들러에 콜백함수를 등록한다.
2. get함수가 종료되어 콜스택이 비어있다.
3. 이벤트가 발생하여 테스크 큐에 콜백함수를 푸시함
4. 이벤트 루프는 콜스택이 비어있으므로 콜스택에 대기하는 콜백함수를 콜스택에 푸시함
5. 콜백함수는 상위스코프도 없어 값의 반환이 불가능하다.
즉, 비동기 함수는 비동기 처리 결과를 외부에 반환할 수 없고, 상위 스코프의 변수에 할당할 수도 없다(Outer lexical environment Reference 가 없음)
또한 에러처리도 곤란하다. 위 흐름처럼 setTimeout함수를 통해 콜백함수를 X초 뒤에 실행토록한다면 try문 안에 있는 setTimeout은 에러가 발생할 수 없고 콜백함수를 등록한 뒤 정상종료 될 것이다. 이 후 callstack이 empty일 때 task queue에 있는 callback function을 호출할 것이다.
Promise의 도입
프로미스는 ES6에서 도입된 표준 빌트인 객체이다. new 키워드로 Promise객체를 생성할 수 있다.
프로미스 객체는 성공시 콜백함수와 실패시 콜백함수를 전달 받는다. 이는 각각 resolve, reject라고 한다.

위 처럼 Promise객체는 'Success'를 출력한다.
Promise의 상태
promise의 상태는 pending과 fulfilled, rejected가 있다.
pending은 비동기 처리가 아직 수행되지 않은 상태이며 fulfilled와 rejected는 비동기 처리가 수행된 상태이며 각각은 성공 또는 실패를 의미한다.
fulfilled상태인 경우 resolve함수를 호출하며 rejected인 경우는 reject함수를 호출한다.
Promise의 후속처리
위 흐름을 보면 resolve인 경우 다음 동작을 수행하고 reject인 경우 에러 처리를 진행해야한다.
이때 후속처리 메서드에 전달한 callback function을 사용한다.
Promise.prototype.then, Promise.prototype.catch
const state = true;
const promise = new Promise((resolve, reject) => {
if(state) {
resolve('Success');
} else {
reject('Failure');
}
}).then((res) => {
console.log(res);
}).catch((rej) => {
console.error(rej);
})
위 코드의 출력은 아래와 같다.

첫번째 callback function은 Promise가 fulfilled상태일 때 호출되며 Promise의 비동기 처리 결과를 인수로 전달 받는다.
두번째 callback function은 Promise가 rejected상태일 때 호출되며 Promise의 에러를 인수로 전달 받는다.
Promise.prototype.finally
이는 Promise의 상태에 상관없이 fulfilled상태인 경우 실행하는 callback함수를 전달할 수 있다.
마이크로테스크큐
callstack이 empty인 경우 task queue에 있는 함수를 실행시킨다. 물론 Promise의 후속처리 메서드 들도 비동기함수가 시케쥴링 한 것이므로 call stack에 바로 들어가지 못하고 어딘가를 거쳐서 들어간다.
하지만 call stack이 아닌 micro task queue에 들어간다. call stack이 empty인 경우 task queue와 micro task queue에 모두 함수가 있다면 micro task queue에 있는 함수를 먼저 event loop가 call stack으로 push한다.
즉 우선순위가 call stack > micro task queue > task queue인 것이다.
setTimeout(() => console.log(1), 0);
Promise.resolve().then(() => console.log(2)). then(() => console.log(3));
위 코드의 실행 결과는 아래와 같다.

즉 마이크로 테스크 큐에 있는 작업들이 먼저 call stack으로 push되고 task queue에 있는 callback이 나중에 실행되는 것을 확인할 수 있었다.
'Js' 카테고리의 다른 글
| MVC 패턴 연습(재고관리 프로그램) 로그 #1 문제정의 (0) | 2025.10.23 |
|---|---|
| Js / JavaScript 문법 / difference between strict equality and loose equality (1) | 2025.01.12 |
| Js / javascript 문법 / async/await 비동기 처리 키워드 (3) | 2024.12.30 |
| 단축평가(short circuit) (3) | 2023.05.03 |
| 데이터 타입 (3) | 2023.01.04 |