Angular 4是否在核心模块单例中提供真正的服务? [英] Angular 4 are services provided in a core module singleton for real?

查看:78
本文介绍了Angular 4是否在核心模块单例中提供真正的服务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试了解angular 4中的核心模块和单例服务. 官方文档( https://angular.io/guide/ngmodule )说了以下内容:

I'm trying to understand core module and singleton services in angular 4. The official documentation (https://angular.io/guide/ngmodule) says the following things:

UserService是应用程序范围内的单例.你不想要每个 模块具有自己的单独实例.然而,确实存在危险 如果SharedModule提供UserService,则会发生这种情况.

UserService is an application-wide singleton. You don't want each module to have its own separate instance. Yet there is a real danger of that happening if the SharedModule provides the UserService.

CoreModule提供UserService. Angular注册该提供商 使用应用程序根注入器,创建 UserService可用于需要它的任何组件,无论是否 组件被急切或延迟加载.

CoreModule provides the UserService. Angular registers that provider with the app root injector, making a singleton instance of the UserService available to any component that needs it, whether that component is eagerly or lazily loaded.

我们建议收集此类一次性使用的类并隐藏它们 CoreModule中的详细信息.简化的根AppModule导入 CoreModule作为应用程序的协调者 整个.

We recommend collecting such single-use classes and hiding their details inside a CoreModule. A simplified root AppModule imports CoreModule in its capacity as orchestrator of the application as a whole.

import { CommonModule }      from '@angular/common';
import { TitleComponent }    from './title.component';
import { UserService }       from './user.service';
import { ModuleWithProviders, NgModule, Optional, SkipSelf }       from '@angular/core';
@NgModule({
  imports:      [ CommonModule ],
  declarations: [ TitleComponent ],
  exports:      [ TitleComponent ],
  providers:    [ UserService ]
})
export class CoreModule {
    constructor (@Optional() @SkipSelf() parentModule: CoreModule) { ... }
}

所以我正在使用提供单例服务的Core Module和构造函数

So I'm using the Core Module providing singleton services, and the constructor

constructor (@Optional() @SkipSelf() parentModule: CoreModule) { ... }

防止多次导入核心模块.

prevent to import the Core Module more than one time.

1)但是,如果我在另一个模块中(例如在延迟加载模块中)提供UserService怎么办?这个延迟加载的模块具有服务的新实例吗?

关于forRoot方法:

And about forRoot method:

@NgModule({
  imports:      [ CommonModule ],
  providers:    [ UserService ]
})
export class CoreModule {
}

static forRoot(config: UserServiceConfig): ModuleWithProviders {
  return {
    ngModule: CoreModule,
    providers: [
      {provide: UserServiceConfig, useValue: config }
    ]
  };
}
}

2)如果我使用AppModule中的CoreModule.forRoot()导入CoreModule,那么UserService会如何?也提供了吗?

2) If I import the CoreModule using CoreModule.forRoot() in the AppModule, what happen to the UserService ? Is it provided too?

谢谢

推荐答案

文档令人困惑,尤其是这一行:

The documentation is confusing, particularly this line:

UserService是应用程序范围内的单例.你不想要每个 模块具有自己的单独实例. 然而,确实存在危险 如果SharedModule提供了UserService ,就会发生这种情况.

UserService is an application-wide singleton. You don't want each module to have its own separate instance. Yet there is a real danger of that happening if the SharedModule provides the UserService.

如果您不使用延迟加载的模块,则不会发生这种情况.让我们来看一个例子.您具有导入B模块的A模块.这两个模块都定义了提供程序:

There's no danger of that happening if you don't use lazy loaded modules. Let's see an example. You have A module that imports B module. Both modules define providers:

@NgModule({
   providers: {provide: 'b', 'b'}
})
export class BModule {}

@NgModule({
   imports: [AModule]
   providers: {provide: 'a', 'a'}
})
export class AModule {}

编译器生成模块工厂时会发生的情况是,它们将这些提供程序合并在一起,并且将仅为一个模块创建工厂 .这是它的外观:

What happens when the compiler generates a module factory is that it merges these providers together and factory only for one module will be created. Here is how it will look:

var AModuleNgFactory = jit_createNgModuleFactory0(

    // reference to the module class
    jit_AppModule1,  

    // array of bootstrap components
    [jit_AppComponent2],

    function (_l) {
        return jit_moduleDef3([

            // array of providers
            jit_moduleProvideDef4(256, 'b', 'b', []),
            jit_moduleProvideDef4(256, 'a', 'a', [])
            ...,
        ]);

您可以看到提供程序已合并.现在,如果您使用相同的提供者令牌定义了两个模块,则这些模块将被合并,而导入另一个模块的模块中的提供者将覆盖导入的模块提供者:

You can see that the providers are merged. Now, if you define two modules with the same provider token, the modules will be merged and the providers from the module that imports the other will override the imported module providers:

@NgModule({
   providers: {provide: 'a', 'b'}
})
export class BModule {}

@NgModule({
   imports: [AModule]
   providers: {provide: 'a', 'a'}
})
export class AModule {}

工厂定义现在看起来像这样:

The factory definition will look like this now:

function (_l) {
    return jit_moduleDef3([

        // array of providers
        jit_moduleProvideDef4(256, 'a', 'a', []),
        ...,
    ]);

因此,无论您导入多少模块,都只会创建一个带有合并提供程序的工厂.并且仅创建一个根注入器.组件创建的注射器不是真正的"注射器-检查此答案以了解原因.

So no matter how many modules you import, only one factory with merged providers is created. And only one root injector is created. The injector that components create is not "real" injector - check this answer to understand why.

此延迟加载的模块具有服务的新实例吗?

This lazy-loaded module has a new instance of the service?

当涉及到延迟加载的模块时,Angular会为它们生成单独工厂.这意味着在它们中定义的提供者不会合并到主模块注入器中.因此,如果延迟加载的模块使用相同的令牌定义了提供程序,则Angular将创建该服务的新实例,即使主模块注入器中已经存在该实例.

When it comes to lazy loaded modules, Angular generates separate factories for them. It means that providers defined in them are not merged into the main module injector. So if a lazy loaded module defines the provider with the same token, Angular will create new instance of that service even if there's already one in the main module injector.

如果我在AppModule中使用CoreModule.forRoot()导入CoreModule

If I import the CoreModule using CoreModule.forRoot() in the AppModule

要了解forRoot的功能,请参见 RouterModule.forRoot(ROUTES)与RouterModule.forChild(ROUTES).

To understand what forRoot does, see RouterModule.forRoot(ROUTES) vs RouterModule.forChild(ROUTES).

这篇关于Angular 4是否在核心模块单例中提供真正的服务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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