2015-04-24 77 views
3

我当然缺少对喷油器的一些基本观点,但我不明白为什么正是这种

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

,这是预期,而这

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

工作

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

将抛出

Error: [$injector:unpr] Unknown provider: $provideProvider <- $provide

从上面的如下,config与供应商的一些特殊关系,同时与run交易情况,但我不确定,使得config块,这样特殊的东西。

因此,是否没有办法在config以外的区域得到$provide,与angular.injector()(虽然它似乎也获得提供者实例)?

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

回答

3

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

实质上,$injectorin config blocks and provider constructor functions$injectoreverywhere else是两个不同的服务具有相同的名称,它是在内部提供者/实例缓存明确定义,连同$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'); 
    ... 
}); 

和在运行时定义新的部件

app.run(function ($provide) { 
    $provide.controller(...); 
    ... 
}); 
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,所以我不知道为什么这种行为显然已经改变。如果有人知道为什么,请让我知道,我会更新我的答案。

+0

谢谢你,迈克尔,这是能够很好地服务于社区的高质量答案。目前,我已经进一步提高了一点,不能从答案中学到任何新东西。我希望有人会分享他对ng内部的知识。我想我必须通过'bootstrap'和'$ injector'并再次研究它们。 – estus

+0

1.4'module'终于暴露了'$ provide'提供的整个API。在之前的版本中并不如此(至少“装饰者”缺失)。 – estus