Jon Gunter
Jon Gunter

Reputation: 2104

AngularJS swallowing certain errors, preventing window's error event from being called

I created a small AngularJS Application that can cause certain errors if specific lines are un-commented. In the HTML of the applciation, I created an inline <script> that listens to the window object's error event.

<script>
      window.addEventListener('error', function (error) {
          console.log('====== An error occured', error);
      })
</script>

In the below, code, I would expect the event listener to be called for all 7 errors (when I un-comment each error and run the program). However, the manually raised errors inside the Service (#7) and the Controller (#3) do not fire the event listener. They do print an error message to the console.

// ERROR 1:
// throw new Error('manually thrown error ouside of AngularJs');

// ERROR 2 (syntax error):
// varasakfsdjklajskdfasdf var adfasdf a var adasdf

class MyController {
    constructor(MyService) {

        MyService.doSomething()

        // ERROR 3:
        // throw new Error('manually thrown error inside of AngularJs');

        // ERROR 4:
        // varasakfsdjklajskdfasdf var adfasdf a var adasdf
    }
}

function configBlock() {
    // ERROR 5:
    // throw new Error('manually thrown error inside of AngularJs');
}

function runBlock() {
    // ERROR 6:
    // throw new Error('manually thrown error inside of AngularJs');
}

class MyService {
    doSomething() {
        // Error 7
        // throw new Error('manually thrown error inside of AngularJs');
    }
}

angular.module('app', []);
angular.module('app').controller('MyController', MyController);
angular.module('app').config(configBlock);
angular.module('app').run(runBlock);
angular.module('app').service('MyService', MyService);

What is going on here, and how can I reliably get every error to raise an event on the window object?

Upvotes: 0

Views: 756

Answers (1)

Jon Gunter
Jon Gunter

Reputation: 2104

After some experimenting, it appears that errors occuring inside services or controllers are delegated to the AngularJS $exceptionHandler where they are caught and logged, preventing them from propagating up to the window object.. If I override that service (see example), I can now intercept these errors and log them or re-throw them so they propagate to the window's error event.

angular.module('app').service('$exceptionHandler', function () {
    return function (error, cause) {
        console.log('ERROR caught by exception handler: ', error, cause)
    }
})

The documentation is not clear on this (what's an AngularJS expression? is a run/config block not one?)

Any uncaught exception in AngularJS expressions is delegated to this service. The default implementation simply delegates to $log.error which logs it into the browser console.

https://docs.angularjs.org/api/ng/service/$exceptionHandler

Upvotes: 1

Related Questions