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));