In Promise-based asynchronous code, rejections are used for error handling. One risk is that rejections may get lost, leading to silent failures. For example:
function main() {
asyncFunc()
.then(···)
.then(() => console.log('Done!'));
}
If asyncFunc()
rejects the Promise it returns then that rejection will never be handled anywhere.
Let’s look at how you can track unhandled rejections in browsers and in Node.js.
Some browsers (only Chrome at the moment) report unhandled rejections.
unhandledrejection
Before a rejection is reported, an event is dispatched that you can listen to:
window.addEventListener('unhandledrejection', event => ···);
The event is an instance of PromiseRejectionEvent
whose two most important properties are:
promise
: the Promise that was rejectedreason
: the value with which the Promise was rejectedThe following example demonstrates how this event works:
window.addEventListener('unhandledrejection', event => {
// Prevent error output on the console:
event.preventDefault();
console.log('Reason: ' + event.reason);
});
function foo() {
Promise.reject('abc');
}
foo();
The output of this code is:
Reason: abc
rejectionhandled
If a rejection is initially unhandled, but taken care of later then rejectionhandled
is dispatched. You listen to it as follows:
window.addEventListener('rejectionhandled', event => ···);
event
is also an instance of PromiseRejectionEvent
.
The following code demonstrates rejectionhandled
:
window.addEventListener('unhandledrejection', event => {
// Prevent error output on the console:
event.preventDefault();
console.log('Reason: ' + event.reason);
});
window.addEventListener('rejectionhandled', event => {
console.log('REJECTIONHANDLED');
});
function foo() {
return Promise.reject('abc');
}
var r = foo();
setTimeout(() => {
r.catch(e => {});
}, 0);
This code outputs:
Reason: abc
REJECTIONHANDLED
The Chrome Platform Status site links to a “Promise Rejection Events Sample” that contains an explanation and code.
Node.js does not report unhandled rejections, but it emits events for them. You can register an event listener like this:
process.on('unhandledRejection', (reason, promise) => ···);
The following code demonstrates how the event works:
process.on('unhandledRejection', (reason) => {
console.log('Reason: ' + reason);
});
function foo() {
Promise.reject('abc');
}
foo();
Note: Node.js v6.6.0+ reports unhandled rejections by default – you don’t need to register an event listener, anymore. Hat tip: @PetrHurtak
The Node.js documentation has more information on the Event unhandledRejection
.