I have this doubt regarding order of execution of Timer functions , microtasks and event listeners :
let promise = Promise.reject("Err@!");
setTimeout(() => {
promise.catch(er => console.log(er, "Caught !")); // (1)
});
window.addEventListener('unhandledrejection', event => console.log("Unhandled Rejection !", event.reason)); // (2)
// Output
// >> Unhandled Rejection ! Err@!
// >> Err@! Caught !
In this, the rejected promise gets caught by Unhandled Rejection
event before being caught by .catch()
inside setTimeout
, the reason for that is:
An "unhandled rejection" occurs when a promise error is not handled at the end of the microtask queue (https://javascript.info/microtask-queue#unhandled-rejection)
Now Considering another case :
let promise = Promise.reject("Err@!");
setTimeout(() => { // (1) ,gets called first
setTimeout(function () { // (3) , gets called at last , (after (2))
promise.catch(er => console.log("caught ", er ))
})
});
setTimeout(function () { // (2) , gets called after (1)
window.addEventListener('unhandledrejection', event => console.log("Unhandled Rejection !", event.reason));
})
// Output
//>> caught Err@!
In this, the promise gets caught by catch
handler in nested setTimeout
, even when in second setTimeout
, the microtask queue is empty and the rejected promise is still not handled by window event listener...
Why so?
By the time the promise rejects (without being handled), the unhandledrejection handler was not attached yet, thus it does not handle the case. You can attach .catch
and .then
handlers whenever you want, and if the Promise already resolved/rejected, they will fire immeadiately (in a microtask).
// first example
1) synchronous execution
- promise rejected
- timeout set
- unhandledrejection event handler attached
2) microtasks
- promise rejects
3) macrotask
- timeout triggers
-> .catch handler gets attached
4) microtasks
.catch gets executed
// second example
1) synchronous execution
- timers get attached
- promise rejects
2) microtasks
- promise rejected
3) macrotasks
- timer 1 done
- timer 3 started
- timer 2 done
- unhandledrejection handler added