8

I've been working with Zone.js and I want to set up logging for any uncaught exceptions. I could set up an error handler, like so:

window.onerror = function(e) { 
    //send an error report to the server
}

But this won't work if an exception is thrown inside a Promise. The nice thing about the Zone error handler is that it hooks into Promises and does fire for exceptions in them, but I can't find a way to actually override or add an error handler after the Zone has been created aside from overriding a bunch of private fields on the Zone.

Is there an actual API for a Zone that I can use to update the error handler, or do I have to change the polyfill where the root Zone is constructed or overwrite private fields or something similar?

Owen K.
  • 81
  • 1
  • 3

3 Answers3

3

for promise uncaught promise error, from zone.js 0.78, you can use this API.

https://github.com/angular/zone.js/pull/627

 window.addEventListener("unhandledrejection", function (event) {
  console.warn("WARNING: Unhandled promise rejection. Shame on you! Reason: "
               + event.reason);
});

window.addEventListener("rejectionhandled", function (event) {
  console.log("Promise rejected! Reason: " + reason);
});
jiali passion
  • 1,691
  • 1
  • 14
  • 19
2

You could try something like this:

<html>
<head>
<script src="https://unpkg.com/zone.js?main=browser"></script>
<script>
Zone.current.fork({
    onHandleError: function(parentZoneDelegate, currentZone, targetZone, error) {
        console.log("Error handled by zone: " + error);
    }
}).run(function () {
    setTimeout(function () {
        console.log("In zone setTimeout")
        throw new Error("Throw in zone setTimeout"); 
    }, 0);
    console.log("Directly in zone");
});
</script>
</head>
<body>
</body>
</html>

Which would catch the exception in the custom handler specified by onHandleError and yield output like this:

Directly in zone (test1.html:14)
In zone setTimeout (test1.html:11 )
Error handled by zone: Error: Throw in zone setTimeout (test1.html:7)

However it seems it does not work if exceptions are thrown directly in the zone. I have filed and issue about this.

Jonas Kello
  • 1,178
  • 2
  • 13
  • 25
2

You have to use runGuarded method instead of run on Zone if you want to handle all types of unhandled exceptions (in simple zones, in setTimeouts or in Promises, etc.)

Here is a sample code to do that:

Zone.current.fork({
  name: 'MyGlobalErrorLoggerZone',
  onHandleError: function(parentZoneDelegate, currentZone, targetZone, error){
     console.log(error);
     // send it to server here.
  }
})
.runGuarded(function(){
   // your application code here...
   // handles errors inside promises
   new Promise(function(resolve, reject){
        reject('Rejecting: Some Error');
   });
    console.log('Running in Zone...', Zone.current.name);
    // handles errors inside timeouts/intervals
    setTimeout(function(){
            console.log('after 1 sec', Zone.current.name);
            throw new Error('This is an error. Make your self log me please.');
    }, 1000);
    // Handles errors throw directly in zone too.
    throw new Error('oops, one more error');
});
Anubhav Gupta
  • 1,176
  • 11
  • 12