Overriding $exceptionHandler

今天碰到結果因為神秘的 cross-domain 引用的 script error 沒有跳在 console 而卡了超久…

$exceptionHandler 的官方文件介紹:

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

在 v1.1.5 的 AngularJS source code 如下:

function $ExceptionHandlerProvider() {
  this.$get = ['$log', function($log) {
    return function(exception, cause) {
      $log.error.apply($log, arguments);
    };
  }];
}

比如說今天針對 angular uncaught exception 我們想要做一些額外的 log,那麼就必須 override 預設的 $exceptionHandler,在隨意寫了一個 override 用的 service 之後你很可能會碰壁…

angular.module('myApp')
.factory('$exceptionHandler', function ($timeout, $log) {
  return function(exception, cause) {
    var args = Array.prototype.slice.call(arguments);
    // delay $log.error by 100ms
    $timeout(function () {
      $log.error.apply($log, args);
    }, 100);
  };
});

錯誤訊息:

Circular dependency found: DepA <- DepB <- DepC

於因出在於其實有部分 AngularJS 原生的 service 都有 inject $exceptionHandler,所以這些 service 是不能再被 inject 到新生的 $exceptionHandler 中的,否則就會造成所謂的 circular dependancy (循環 dependancy?)

不能 inject 到 override 用的 $exceptionHandler 的原生 service 表列如下:

  • $rootScope
  • $timeout
  • $compile
  • $interpolate
  • $q

另外就是 試圖 inject 其它 module 的 service 進 $exceptionHandler 時候,那些 service 也不能夠包含以上的原生 service dependancy