let p1 = Promise.resolve(1);
p1.then(console.log)
.catch(console.log)
.finally(()=>{
console.log(2)
})
console.log("코드 종료");
비동기함수는 이벤트루프에 콜백은 추가하고 호출은 이벤트루프에 위임한다고 했다.
promise객체도 비동기작업으로 바로 fullfilled되어도 동기식코드가 수행된후 이벤트루프에의해 호출된다.
이벤트루프에대해 자세히 알아보자
V8엔진에는 마이크로태스크 큐(microtask queue)로 이러한 비동기작업들을 처리한다고 되어있다.
마이크로태스크 큐는 먼저 들어온 작업을 먼저 실행한다(FIFO, first-in-first-out).
실행할 것이 아무것도 남아있지 않을 때만 마이크로태스크 큐에 있는 작업이 실행되기 시작한다.
p1.then(console.log); promise 핸들러가 마이크로태스크큐에 추가되고 console.log("코드 종료");가 수행된후 더이상 수행할 작업이 없을때 엔진은 마이크로태스크큐에 있는 핸들러들을 순서대로 처리한다.
처리되지 못한 거부(unhandledrejection)
unhandledrejection은 마이크로태스크 큐 끝에서 promis핸들러에서 처리되지 못할 때 발생한다.
let p1 = new Promise(()=>{
a();
});
p1.then(console.log)
.finally(()=>{
console.log(2)
})
window.addEventListener('unhandledrejection',(event)=>{
console.log('unhandledrejection : '+event.reason);
});
unhandledrejection에서 검출하는것은 에러객체가 아니고 이벤트이기때문에 event.reason을 확인해야 한다.
unhandledrejection는 마이크로태스크큐에서 발생하는 것이기때문에 오직 마이크로태스크큐에 들어있는 핸들러가 처리되지 않을때만 발생하는 이벤트다.
let promise = Promise.reject(new Error("프라미스 실패!"));
setTimeout(() => promise.catch(err => console.log('잡았다!')), 1000);
window.addEventListener('unhandledrejection',(err)=>{
console.log('unhandledrejection : '+err.reason);
});
Promise.reject로 reject된 promise객체가 존재하지만 마이크로태스크큐에는 처리할 핸들러가 존재하지 않는다.
setTimeout으로 핸들러는 1초후에 마이크로태스크큐에 추가되기때문에 unhandledrejection이벤트가 발생한다.
1초후에 추가된 핸들러는 reject된 promise객체가 있으므로 실행된다.