마이크로태스크

let promise = Promise.resolve();

promise.then(() => alert("프라미스 성공!"));

alert("코드 종료"); // 얼럿 창이 가장 먼저 뜹니다.

예시를 실행하면 '코드 종료’가 먼저, '프라미스 성공!'이 나중에 출력된다. 이는 내부 동작 방식의 차이 때문이다.

마이크로태스크 큐

비동기 처리를 위하여 ECMA에서 PromiseJobs라는 내부 큐(internal queue)를 명시하였다. (V8 엔진에서는 '마이크로태스크 큐(microtask queue)'라고 부른다. 이것이 더 통용되는 말)

+) 프라미스 핸들러 (.then/catch/finally)는 비동기적으로 실행된다. 그러므로 모든 핸들러 체이닝보다 그 다음 동기 로직이 먼저 실행된다.

만약 비동기식들의 순서를 보장하기 위해서는 then 체이닝을 이용하면 된다.

Promise.resolve()
  .then(() => alert("프라미스 성공!"))
  .then(() => alert("코드 종료"));

처리되지 못한 거부

프라미스와 에러 핸들링에서 학습한 를 기억하고 계시나요?

이제 자바스크립트 엔진이 어떻게 처리되지 못한 거부(unhandled rejection)를 찾는지 정확히 알 수 있습니다.

'처리되지 못한 거부’(unhandledrejection 이벤트 발생)는 마이크로태스크 큐 끝에서 프라미스 에러가 처리되지 못할 때 발생한다.

일반적으로 모든 비동기에 대하여 에러가 잡히거나 없으면 문제가 되지 않는다. 다만, 에러가 발생하였고 마이크로태스크큐가 비워진 경우에 unhandledrejection 이벤트가 발생한다.

let promise = Promise.reject(new Error("프라미스 실패!"));

// 프라미스 실패!
window.addEventListener('unhandledrejection', event => alert(event.reason));
그런데 만약 아래와 같이 setTimeout을 이용해 에러를 나중에 처리하면 어떤 일이 생길까요?

let promise = Promise.reject(new Error("프라미스 실패!"));
setTimeout(() => promise.catch(err => alert('잡았다!')), 1000); //늦게 catch를 붙임.

// Error: 프라미스 실패!
window.addEventListener('unhandledrejection', event => alert(event.reason));