AngularJS Provider依赖注入 - 在提供程序中使用$ log [英] AngularJS Provider dependency injection - using $log in provider

查看:160
本文介绍了AngularJS Provider依赖注入 - 在提供程序中使用$ log的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题很简单:使用AngularJS我们无法将$ log注入提供者。

The problem is simple: using AngularJS we can't inject $log into provider.

angular.module('my.module', [])
    .provider('myProvider', function ($log, $logProvider) {
        $log.log("Aloha!"); // Unknown provider: $log
        $logProvider.log("Hi!"); // undefined is not a function: $logProvider has no `log` method 
        this.$get = function($log) {
            $log.log("Hello!"); // Everything is ok here
        };
    });

是的,我们可以注入 $ logProvider ,但它没有必要的方法( .log .error 等)。

Yes, we can inject $logProvider, but it has no needed methods(.log, .error, etc.).

是的,我们可以注入 $ logProvider ,然后手动调用 $ logProvider。$ get(),但是我们将无法使用装饰器中的其他逻辑。

Yes, we can inject $logProvider, and then manually call $logProvider.$get(), but we will unable to use additional logic from decorators.

是的,我们可以编写自己的logProvider,但我想知道为什么Angular不支持此功能开箱即用。

Yes, we can write our own logProvider, but I wonder why Angular don't support this feature out-of-the-box.

那么,我们不能在提供商的'真正的角度方式'中使用控制台吗?这个事实很奇怪。很难过。

So, we can't use console in 'true angular way' in provider? That fact is very strange. And sad.

问题:我如何在提供商中以真正的角度方式使用控制台?

The question: how I need to use console in "true Angular way" in providers?

我无法找到有关此问题的任何解释。
Angular Developers Guide说我们需要在每个地方使用$ log而不是控制台。

I was unable to find any explanations of this problem. Angular Developers Guide says that we need to use $log everywhere instead of console.

推荐答案

提供商过早运行创建任何服务或者换句话说,提供者的$ get是服务构造函数,它在模块的配置阶段之后被实例化(当它通过依赖注入首次访问时,注入器实例化构造函数并将其保持为单例) 。并且提供程序在配置阶段期间或之前运行(因为提供程序方法用于在模块的 config 阶段配置服务)。这意味着$ log服务尚不可用。

Providers run too early before any services are created or in other words provider's $get is the service constructor and it gets instantiated after the config phase of the module (and when it is accessed for the first time via dependency injection the injector instantiates the constructor and keep it as singleton). And providers run during or before the config phase (since the provider methods are used for configuring the service during the config phase of the module). Which means $log service is not available yet.

$ logProvider。$ get 将为您提供logservice的构造函数,您可以自己创建一个它的实例调用 $ injector.instantiate($ logProvider。$ get)但问题是它依赖于尚未实例化的窗口服务,所以最终你的记录器实例化将会失败。

$logProvider.$get will give you the constructor for logservice, you could yourself create an instance of it by calling $injector.instantiate($logProvider.$get) but the problem is that it has a dependency on window service which has not bee instantiated yet, so ultimately your logger instantiation will fail.

所以我能想到的一种方法是从另一个注入器获取$ log,即 angular.injector(['ng'] ).get('$ log')

So one way i could just think of is to get $log from another injector, i.e angular.injector(['ng']).get('$log').

ie

angular.module('my.module', [])
  .provider('myProvider', function ($log, $logProvider) {
    var $log =  angular.injector(['ng']).get('$log');
    $log.log("Aloha!"); 

    this.$get = function($log) {
        $log.log("Hello!"); // Everything is ok here
    };
});

Plnkr

Plnkr

或者另外一种方法就是疯狂地实例化它,在这种情况下实例化它的依赖服务它只是 $ window (甚至提供全局窗口对象作为本地人)。

Or another way just go crazy instantiate it on your own, instantiating its dependent services in this case it is just the $window (or even provide global window object as locals).

 .provider('myProvider', function ($logProvider,$injector, $windowProvider) {
    //get window service, if you want to really provide window service instance itself, or just provide the global window object
    var window = $injector.instantiate($windowProvider.$get);
    //Get log provider providing locals for $window
    var $log =  $injector.instantiate($logProvider.$get,{$window:window})

    $log.log("Aloha!");// Everything is ok here too

    this.$get = function($log) {
        $log.log("Hello!"); // Everything is ok here
    };

});

Plnkr

Plnkr

添加不同的注释:尝试访问<$ c $时会看到相同的行为c> $ log 在应用程序的配置阶段也提供服务。但有时由于装饰器的工作方式,你仍然可以通过使用虚拟装饰器强制创建早期服务来使用它。

Just to add a different note: You will see the same behavior while trying to access the $log service during the config phase of the app as well. But sometimes due to the way decorators work you could still make use of it by forcing an early service creation by using a dummy decorator.

ie:

.config(function($provide){
   //Just a dummy decorator
   $provide.decorator('$log', function($delegate){
      return $delegate;
  });

}).config(function($logProvider){
   //get logger instance
   var log = $logProvider.$get();
   log.debug("Got it");
});

Plnkr

Plnkr

所以最终的想法是,当你需要在实例化之前使用服务时,你需要通过解析所有依赖关系来手动实例化它等等。

So ultimately the idea is that, when you need to use a service before it has been instantiated yet, you would need to manually instantiate it by resolving all of its dependencies and so on.

这篇关于AngularJS Provider依赖注入 - 在提供程序中使用$ log的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆