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 aPromise
is 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...).