$提供外部配置块

时间:2015-04-24 18:22:39

标签: angularjs internals angularjs-injector

我当然错过了关于注射器的一些基本观点,但我不明白为什么会这样呢

angular.module('app').config(function ($provide) {
    ...
});

和这个

angular.module('app').config(function ($injector) {
    $injector.invoke(function ($provide) { ... });
});

按预期工作,而这

app.run(function($provide) {
    ...
});

将抛出

  

错误:[$ injector:unpr]未知提供商:$ provideProvider< - $ provide

如上所述,config与提供商有一些特殊关系,run处理实例,但我不确定是否会导致config阻止特殊。

因此,无法前往$provide config个{}}区块,例如使用angular.injector()(虽然它似乎也获得了提供者实例)?

除了好奇之外,这个问题还有一些实际的考虑因素。在1.4中,所有$provide函数都暴露给模块,但1.3的情况并非如此。

2 个答案:

答案 0 :(得分:5)

config()函数的目的是允许您执行一些影响整个应用程序的全局配置 - 包括服务,指令,控制器等。因此, config()块必须先运行。但是,您仍然需要一种方法来执行上述配置,并使其可用于应用程序的其余部分。这样做的方法是使用提供程序

是什么让提供者"特别"是他们有两个初始化部分,其中一个与config()块直接相关。看看下面的代码:

app.provider('myService', function() {
    var self = {};    
    this.setSomeGlobalProperty = function(value) {
        self.someGlobalProperty = value;
    };

    this.$get = function(someDependency) {
        this.doSomething = function() {
            console.log(self.someGlobalProperty);
        };
    };    
});

app.config(function(myServiceProvider) {
    myServiceProvider.setSomeGlobalProperty('foobar');
});

app.controller('MyCtrl', function(myService) {
    myService.doSomething();
});

当您将提供者注入config()函数时,您可以访问任何 $get函数(从技术上讲,您可以访问$get函数,但称它不会工作)。这样你就可以做任何你可能需要做的配置。那是第一个初始化部分。值得一提的是,即使我们的服务名为myService,您也需要在此处使用后缀Provider

但是当你将同一个提供者注入任何其他地方时,Angular会调用$get()函数并注入它返回的任何内容。那是第二个初始化部分。在这种情况下,提供者的行为就像普通服务一样。

现在关于$provide$injector。由于它们是"配置服务",因此我无法在config()块之外访问它们。如果可以的话,那么你可以在之后创建一个工厂,它已经被其他服务使用了。

最后,我还没玩过v1.4,所以我不知道为什么这种行为显然已经改变了。如果有人知道原因,请告诉我,我会更新我的答案。

答案 1 :(得分:3)

经过一些Angular注射器研究后,我能够对我自己的问题给出详尽的答案。

基本上,$injector in config blocks and provider constructor functions$injector everywhere else是两个具有相同名称的不同服务,它们在内部提供程序/实例缓存中明确定义,并与{{ 1}}(这个在提供程序缓存中定义,因此只能在$provide中注入。)

虽然由于可能的竞争条件通常不推荐使用,但可以在配置阶段结束后将内部服务公开给实例缓存并使配置特定的config$provide可用于注入:

$injector

可能的应用程序随时(如果可能)配置服务提供商

app.config(function ($provide, $injector) {
  $provide.value('$providerInjector', $injector);
  $provide.value('$provide', $provide);
});

并在运行时定义新组件

app.run(function ($providerInjector) {
  var $compileProvider = $providerInjector.get('$compileProvider');
  ...
});