可以扩展Angular JS 1.2.18 $ log功能吗?

时间:2014-12-26 19:16:25

标签: javascript angularjs toastr angularjs-decorator

我想弹出一个toastr消息来显示$ log消息。即:

$log.info('test'));

似乎在AngularJS 1.2.19及更高版本中,$provide.decoratorextend the functionality of $log的绝佳方式。当然,我使用的是1.2.18。在1.2.18中有没有办法做到这一点?

理想情况下,我希望扩展现有功能,而不是完全覆盖它。

我不想修改Angular来源。

1 个答案:

答案 0 :(得分:3)

装饰器机制是创建获取先前定义并返回其新版本的提供者的简写。

因此,您可以按如下方式模仿此功能:

module.provider('$log', function ($logProvider) {
    // $logProvider here is the one previously defined, from 'ng'
    // unless someone else is overriding too.
    this.$get = function ($injector) {
        // Invoke the original provider.
        var $log = $injector.invoke($logProvider.$get);
        var oldInfo = $log.info;
        // Override the method.
        $log.info = function info() {
            oldInfo.apply(this, arguments);
            // (not actually useful to alert arguments; just an example)
            alert(arguments);
        }
        return $log;
    }
});

当然,这会修改所有依赖项的对象,即使它们对标准$log接口非常满意,也意味着您无法直接在应用程序中查看哪些服务依赖于标准接口这取决于你的增强界面。如果您只想通过换行来更改现有方法的行为(例如,将日志发送到您的服务器,或者如您在问题中提到的那样显示烤面包机),这可能很有用,但对于添加其他内容可能是一个冒险的选择现有呼叫者不期望的方法,您可能会意外破坏与标准接口的兼容性。

相反,最好提供一个新服务,您可以在需要扩展名的地方使用该服务,并将内置$log接口作为标准配置。通过这种方式,可以更容易地区分并避免标准调用者中的意外行为更改。这看起来类似于上面的内容,但在细节上略有不同:

module.provider('anotherLog', function ($logProvider) {
    this.$get = function ($injector) {
        var $log = $injector.invoke($logProvider.$get);

        // Create a new object rather than extending the existing one in-place.
        // This way the new method is only visible to callers that request
        // 'anotherLog' instead of just '$log'.
        var anotherLog = angular.extend(Object.create($log), {
            sayHello: function sayHello() {
                console.log('Hello!');
            }
        })

        return anotherLog;
    }
});

这两种方法都利用了这样一个事实:在app初始化过程中,一个单独的提供者注入器"用于处理提供者之间的依赖关系。这与创建应用程序后使用的主$injector不同。提供者注入器包含到目前为止已定义的所有提供者,但不包含诸如$log之类的结果服务。提供者函数本身注入了提供者注入器,而其$get方法(如这些示例所示)注入了主$injector

由于这种区别,如果您依赖任何其他服务来显示您的烤面包机,则必须依赖它们来获取$get方法本身而不是整个提供者。这将允许您访问主$injector中的服务,而不仅仅是提供者注入器中的提供者。