마이크로태스크

마이크로태스크

프로미스 핸들러는 항상 비동기적으로 실행된다.
.then().catch().finally() 와 같은 함수 뒤에 적혀 있는 코드가 있다면 뒤에 적혀 있는 코드가 항상 먼저 실행괴고 그 다음 실행된다.

1
2
3
4
5
let promise = Promise.resolve();

promise.then(() => console.log('프라미스 성공'));

console.log('코드 종료'); //이 로그가 가장 먼저 실행된다.

마이크로태스크 큐

비동기 작업을 위한 큐가 있다. ECMA에서는 PromiseJobs라고 부른다. V8 엔진에서는 이를 마이크로테스크 큐 라고 부른다.

  • FIFO 정책을 따른다.
  • 실행될 코드가 전혀 없을 때 마이크로테스크 큐에 작업이 실행된다.

.then().catch().fianlly() 는 항상 비동기적으로 실행 된다. 이 작업들은 모두 마이크로테스크 큐에 담기게 되고, 현제 실행될 코드가 없고 이전에 먼저 큐에 담겨진 코드가 모두 실행된 이후에 해당 작업이 실행된다.

처리되지 못한 거부

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

정상적인 경우 .catch()를 호출해서 에러를 처리하지만 그렇지 못한 경우 엔진은 마이크로태스크 큐가 빈 이후에 unhandlerejection 이벤드를 트리거 한다.

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

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

그런데 만약 setTimout()을 사용하여 에러를 나중에 처리하면

1
2
3
4
5
let promise = Promise.reject(new Error("프라미스 실패!"));
setTimout(() => promise.catch(err => console.lot('잡았다')), 1000)


window.addEventListener('unhandlerejection', event => console.log(event.reason));

프라미스 실패가 먼저, 잡았다가 나중에 출력되는 것을 볼 수 있다.

unhandlerejection은 마이크로테스크 큐에 모든 작업이 완료 되면 트리거 된다. 엔진은 프라미스를 검사하고 하나라도 거부 상태이면 핸들러를 트리거 한다.
.catch()역시 트리거 된다. 다만 .catch()unhandledrejection이 발생한 이후에 트리거 된다.