Angular JS:为什么module.config注入和控制器注入之间的区别?

时间:2022-02-25 11:24:36

This is something that I could not figure out from digging into the AngularJS code, maybe you can help solve the mystery.

这是我无法从挖掘AngularJS代码中找到的东西,也许你可以帮助解决这个谜团。

To show it, I added a service to AngularJS seed project:

为了展示它,我向AngularJS种子项目添加了一项服务:

function MyServiceProvider() {
    console.log('its my service');
    this.providerMethod = providerMethod;

    function providerMethod() {
        console.log('its my service.providerMethod');
    }

    this.$get = $get;

    function $get() {
        var innerInjectable = {
             name: 'stam'
        };
        return innerInjectable;
    }
}

var serviceModule = angular.module('myApp.services', []).
    value('version', '0.1').
    provider('myservice',MyServiceProvider);

You can see that this provider exposes $get and a certain 'providerMethod'.

您可以看到此提供程序公开$ get和某个'providerMethod'。

Now, for the injection usage: If we call config, we can inject the whole class and get access to the 'outer' provider method:

现在,对于注入用法:如果我们调用config,我们可以注入整个类并访问'外部'提供者方法:

serviceModule.config(function(myserviceProvider) {
    console.log('myServiceProvider:',myserviceProvider);
    myserviceProvider.providerMethod();
});

But when we inject this to a controller (note the Provider-less name), only the $get return value is exposed:

但是当我们将它注入控制器(注意无提供者名称)时,只会暴露$ get返回值:

function MyCtrl1(myservice) {
    console.log('MyCtrl1.myservice =',myservice,myservice.name);
}
MyCtrl1.$inject = ['myservice'];

Console output follows as it should: its my service myServiceProvider: Constructor {providerMethod: function, $get: function} its my service.providerMethod MyCtrl1.myservice = Object {name: "stam"} stam

控制台输出应该如下:它的我的服务myServiceProvider:构造函数{providerMethod:function,$ get:function}它的我的service.providerMethod MyCtrl1.myservice = Object {name:“stam”} stam

Can any one explain the difference? The reason? many thanks for any thought

任何人都可以解释这个区别吗?原因?非常感谢任何想法

Lior

PS: I've seen this technique in angular-ui new ui-router (excellent project!). I need access to the outer provider class to do injection in jasmine and other places - to no avail

PS:我在angular-ui新的ui-router(优秀项目!)中看到了这种技术。我需要访问外部提供者类来在茉莉花和其他地方进行注射 - 无济于事

2 个解决方案

#1


9  

A provider is responsible for creating instances. In your example, you created a provider explicitly, but the truth is that every service has a provider, even if it's created automatically for it. [module].service() and [module].factory() are just shortcuts for [module].provider().

提供者负责创建实例。在您的示例中,您明确地创建了一个提供程序,但事实是每个服务都有一个提供程序,即使它是为它自动创建的。 [module] .service()和[module] .factory()只是[module] .provider()的快捷方式。

[module].config() is run during provider registrations and configurations so you get a change to access providers and do stuff with them. It's a place for configuration of things, hence the name.

[module] .config()在提供程序注册和配置期间运行,因此您可以更改访问提供程序并对其进行操作。这是一个配置事物的地方,因此得名。

From the documentation (http://docs.angularjs.org/guide/module):

从文档(http://docs.angularjs.org/guide/module):

Configuration blocks - get executed during the provider registrations and configuration phase. Only providers and constants can be injected into configuration blocks. This is to prevent accidental instantiation of services before they have been fully configured.

配置块 - 在提供程序注册和配置阶段执行。只有提供程序和常量才能注入配置块。这是为了防止在完全配置服务之前意外实例化服务。

Controllers, in the other hand, are instantiated AFTER services have been configured, so you're not supposed to mess with providers anymore. Everything has already been configured. You're ready to get their products now. In this phase, the injector just can't inject providers anymore, just instances (services) created by them.

另一方面,控制器是在配置了AFTER服务后实例化的,所以你不应该再混淆供应商了。一切都已经配置好了。你现在准备好了他们的产品。在这个阶段,注入器不能再注入提供者,只是它们创建的实例(服务)。

If you register a service myService...

如果您注册服务myService ...

myModule.service('myService', function() {
    // this is your service constructor
});

then you can access its provider, myServiceProvider, in a config function...

然后你可以在配置函数中访问它的提供者myServiceProvider ...

myModule.config(function(myServiceProvider) {
    // to stuff with your provider here
});

but by the time controllers are being instantiated, you're supposed to ask for services, not their providers, so this will not work...

但是当控制器被实例化时,你应该要求服务,而不是他们的提供者,所以这不会起作用......

myModule.controller(function(myServiceProvider) {
    ...
});

whereas this will be fine...

这样会很好......

myModule.controller(function(myService) {
    ...
});

If you're finding yourself needing to do configuration in a controller, you should stop and rethink the place of responsibilities.

如果您发现自己需要在控制器中进行配置,则应该停下来并重新考虑责任的位置。

#2


4  

From the Angular mailing list I got an amazing thread that explains service vs factory vs provider and their injection usage. I decided to put it in its own question here

从Angular邮件列表中我得到了一个惊人的线程,解释了服务与工厂与提供商及其注入使用情况。我决定在这里提出它自己的问题

the specific answer is: it is so by design, to allow configuration of the provider at config time.

具体的答案是:它是设计的,允许在配置时配置提供者。

#1


9  

A provider is responsible for creating instances. In your example, you created a provider explicitly, but the truth is that every service has a provider, even if it's created automatically for it. [module].service() and [module].factory() are just shortcuts for [module].provider().

提供者负责创建实例。在您的示例中,您明确地创建了一个提供程序,但事实是每个服务都有一个提供程序,即使它是为它自动创建的。 [module] .service()和[module] .factory()只是[module] .provider()的快捷方式。

[module].config() is run during provider registrations and configurations so you get a change to access providers and do stuff with them. It's a place for configuration of things, hence the name.

[module] .config()在提供程序注册和配置期间运行,因此您可以更改访问提供程序并对其进行操作。这是一个配置事物的地方,因此得名。

From the documentation (http://docs.angularjs.org/guide/module):

从文档(http://docs.angularjs.org/guide/module):

Configuration blocks - get executed during the provider registrations and configuration phase. Only providers and constants can be injected into configuration blocks. This is to prevent accidental instantiation of services before they have been fully configured.

配置块 - 在提供程序注册和配置阶段执行。只有提供程序和常量才能注入配置块。这是为了防止在完全配置服务之前意外实例化服务。

Controllers, in the other hand, are instantiated AFTER services have been configured, so you're not supposed to mess with providers anymore. Everything has already been configured. You're ready to get their products now. In this phase, the injector just can't inject providers anymore, just instances (services) created by them.

另一方面,控制器是在配置了AFTER服务后实例化的,所以你不应该再混淆供应商了。一切都已经配置好了。你现在准备好了他们的产品。在这个阶段,注入器不能再注入提供者,只是它们创建的实例(服务)。

If you register a service myService...

如果您注册服务myService ...

myModule.service('myService', function() {
    // this is your service constructor
});

then you can access its provider, myServiceProvider, in a config function...

然后你可以在配置函数中访问它的提供者myServiceProvider ...

myModule.config(function(myServiceProvider) {
    // to stuff with your provider here
});

but by the time controllers are being instantiated, you're supposed to ask for services, not their providers, so this will not work...

但是当控制器被实例化时,你应该要求服务,而不是他们的提供者,所以这不会起作用......

myModule.controller(function(myServiceProvider) {
    ...
});

whereas this will be fine...

这样会很好......

myModule.controller(function(myService) {
    ...
});

If you're finding yourself needing to do configuration in a controller, you should stop and rethink the place of responsibilities.

如果您发现自己需要在控制器中进行配置,则应该停下来并重新考虑责任的位置。

#2


4  

From the Angular mailing list I got an amazing thread that explains service vs factory vs provider and their injection usage. I decided to put it in its own question here

从Angular邮件列表中我得到了一个惊人的线程,解释了服务与工厂与提供商及其注入使用情况。我决定在这里提出它自己的问题

the specific answer is: it is so by design, to allow configuration of the provider at config time.

具体的答案是:它是设计的,允许在配置时配置提供者。