We added an event handler for "unhandledRejection" in our node application, this handler terminates the process (as node says will be the default soon).
However we're seeing what appears to be superfluous (or at least premature) events.
We're using Q.allSettled (which handles rejected promises), I see in the debugger that the promise array has two elements, the first rejected and the second pending (it will be resolved). After placing breakpoints in the unhandledRejection handler and in the then following the allSettled, I get the unhandledRejection first and immediately afterwards the then (so the rejection is handled).
The documentation for unhandledRejection says (emphasis mine):
The
'unhandledRejection'event is emitted whenever aPromiseis rejected and no error handler is attached to the promise within a turn of the event loop.
My assumption is that the mechanism that created the array of promises blocked between the first promise being rejected and the creation of the array but I haven't been able to reproduce this in a toy example.
The best minimal example I've been able to come up with is a bit contrived but I think it has the same root cause as our code. Am I missing something here? How can node make unhandledRejection terminate the process by default if this is possible?
process.on("unhandledRejection", (reason, p) => {
console.error(`### Got unhandled rejection: '${reason}'`);
});
function doesNotFireUnhandledRejection() {
let rejected = Promise.reject('an error');
return new Promise((resolve, reject) => {
resolve(rejected);
})
.catch(err => console.log("Caught:", err));
}
function firesUnhandledRejection() {
let rejected = Promise.reject('an error');
return new Promise((resolve, reject) => {
setTimeout(() => resolve(rejected), 0);
})
.catch(err => console.log("Caught:", err));
}
BTW, The same behaviour happens with setImmediate but not with process.nextTick (although I could swear that last week process.nextTick did cause the event to fire...).