如何重写$ exceptionHandler实现


73

每当抛出javascript异常时,我们还想做一些额外的事情。

从以下文档$exceptionHandler

角度表达式中任何未捕获的异常都委托给此服务。默认实现只是将$ log.error委托给浏览器控制台。

它说“默认实现”的事实使我认为有一种方法可以为服务提供我们自己的实现,并在引发异常时做我们想要的事情。我的问题是,你如何做到这一点?我们如何使所有异常都保留给该服务,然后提供我们希望发生的功能?


1
请选择“ $ provide.decorator”解决方案作为该问题的答案。
wizulus 2014年

Answers:


173

我为此找到的另一个选择是$exceptionHandler通过$ provide.decorator函数“装饰” 。如果要将原始实现用作自定义实现的一部分,则可以为您提供参考。因此,您可以执行以下操作:

mod.config(function($provide) {
    $provide.decorator("$exceptionHandler", ['$delegate', function($delegate) {
        return function(exception, cause) {
            $delegate(exception, cause);
            alert(exception.message);
        };
    }]);
});

它将执行原始异常处理程序所做的事情,以及自定义功能。

请参阅此更新的小提琴


2
为此+1,这无疑是处理问题的更好方法。
Roy Truelove 2013年

使用了它,但是似乎无法正确缩小!
罗杰·法尔(Roger Far)

它可以像在编辑中一样使用数组符号吗?就像在其他任何依赖注入用于最小化的地方一样,您必须在这里这样做。
dnc253 2014年

@ dnc253是的,我弄清楚之后才应用了编辑。
罗杰·法尔(Roger Far)

1
我建议您注意:这会吞噬您肯定不希望发生的业力单元测试中的所有异常。
雨果·德·亨里格

56

您可以$exceptionHandler通过创建具有相同名称的服务来覆盖功能:

var mod = angular.module('testApp', []);

mod.factory('$exceptionHandler', function () {
    return function (exception, cause) {
        alert(exception.message);
    };
});

有关示例,请参见此小提琴。如果注释掉出厂定义,$exceptionHandler您将看到错误将记录到控制台而不是发出警报。

这是一个组线程,其中包含注入其他服务(例如$httpusing)的示例$injector

注意:如果您不想覆盖$exceptionHandler(或其他内置服务)的现有功能,请参见此答案以获取有关如何装饰服务的信息。


因此,基本上您可以覆盖任何服务,最后一个定义胜出,对吗?
dnc253

9
我非常喜欢@ dnc253的解决方案。通过使用“装饰器”功能,您可以保留现有行为并允许其他装饰器参与该操作。如果您由于其他原因已经在其他地方完成此操作,则此命令将破坏已有的所有内容,包括您自己的代码。
Brian Genisio

2
我完全同意装饰器是一种更清洁的方法。
Gloopy

1
尽管装饰器似乎更好,但是如果您想使用工厂或在module.config时未初始化的任何其他东西,这似乎是一个不错的解决方案
Hoppe

1
如果您是最后一个定义,那么在单独的包含的模块中进行配置是否可以正常工作?
Casey 2015年

-5

您可以覆盖任何服务/工厂甚至$ cookieStore。如果您想要一个完整的可配置对象,这是一个非常好的示例

var myApp = angular.module('myApp', []);

//provider style, full blown, configurable version     
myApp.provider('helloWorld', function() {

    this.name = 'Default';

    this.$get = function() {
        var name = this.name;
        return {
            sayHello: function() {
                return "Hello, " + name + "!"
            }
        }
    };

    this.setName = function(name) {
        this.name = name;
    };
});

//hey, we can configure a provider!            
myApp.config(function(helloWorldProvider){
    helloWorldProvider.setName('World');
});


function MyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) {

   helloWorld.sayHello(),
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.