Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom error handler in Zone.js

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?

like image 242
Owen K. Avatar asked Aug 31 '16 23:08

Owen K.


3 Answers

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);
});
like image 105
jiali passion Avatar answered Sep 20 '22 20:09

jiali passion


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.

like image 33
Jonas Kello Avatar answered Sep 20 '22 20:09

Jonas Kello


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');
});
like image 27
Anubhav Gupta Avatar answered Sep 17 '22 20:09

Anubhav Gupta