Angular 4 的核心模块中的服务真的是单例提供的吗?

2023-12-09

我试图理解 Angular 4 中的核心模块和单例服务。 官方文档(https://angular.io/guide/ngmodule)说了以下几件事:

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

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

我们建议收集此类一次性使用的类并隐藏它们 CoreModule 内的详细信息。简化的根 AppModule 导入 CoreModule 作为应用程序的协调器 所有的。

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) { ... }
}

所以我使用提供单例服务的核心模块和构造函数

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

防止多次导入核心模块。

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

关于 forRoot 方法:

@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 会发生什么?也提供了吗?

Thanks


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

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

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

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

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

当编译器生成模块工厂时会发生什么merges这些供应商一起和工厂仅适用于一个模块将被创建。其外观如下:

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', [])
            ...,
        ]);

您可以看到提供商已合并。现在,如果您使用以下命令定义两个模块相同的提供商令牌,模块将被合并,导入另一个模块的提供程序将覆盖导入的模块提供程序:

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

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

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

function (_l) {
    return jit_moduleDef3([

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

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

这个延迟加载的模块有一个新的服务实例吗?

当涉及到延迟加载模块时,Angular 会生成separate为他们建造工厂。这意味着其中定义的提供程序不会合并到主模块注入器中。因此,如果延迟加载的模块使用相同的令牌定义提供者,Angular 将创建该服务的新实例,即使主模块注入器中已经有一个实例。

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

要了解什么forRoot确实,看到RouterModule.forRoot(ROUTES) 与 RouterModule.forChild(ROUTES).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Angular 4 的核心模块中的服务真的是单例提供的吗? 的相关文章

随机推荐

  • Tapestry:字符编码问题

    我有一个 Tapestry 应用程序 它从表单中检索数据 将其写入数据库 然后显示结果 只要不使用特殊字符 一切都可以正常工作 例如 文本 Test 将导致 Test 我猜这个问题与错误的字符编码设置有关 Tapestry java 类 C
  • 删除多个实体上的表行拆分时出错

    我想删除拆分为两个实体的表行 如果我尝试删除主要实体 如果之前我没有使用以下命令加载相关的其他实体 则会收到错误消息context Entry Reference 当我要删除整行时 之前检索相关实体是不是有点愚蠢 如果我继续评论 我会收到以
  • 折叠表达式:替换特定类型但转发所有其他类型:如何实现这一点?

    我试图替换折叠表达式中的特定类型 同时简单地转发所有其他类型 但失败了 As std forward需要显式模板专门化我尝试提供另一组模板化重载 但是这些尚未考虑重载解决方案如果这有效的话 无论如何都会导致不明确的函数调用 第二次尝试是专门
  • 在 Python 3 中调用命令行参数

    我正在用 Python 3 编写一个程序 该程序将从 csv 文件中获取数据 对其进行调整并将新数据写入由用户命名的 csv 文件 我只是想了解命令行部分 我希望它能够以这种格式正确执行 program py input csv outpu
  • 如何在聚合物组件内部使用react?

    似乎可以在聚合物网络组件中使用 React 但我找不到工作示例 只能this 但似乎已经过时了 HTML
  • java 哪个布局管理器适合这个任务?

    我有一个 JPanel 父级 里面有 3 个 JPanel 子级 它们目前都使用 GridLayout 并共同表示一个 UML 类 问题是 当我添加新属性或方法时 所有 3 个 JPanel 都会增长到相同的大小 欲望行为是 无论何时添加方
  • 固定与绝对

    因此 我检查了该网站 发现一些问题与我正在寻找的内容很接近 但并不完全相同 我试图弄清楚如何定位元素 以便在滚动 向上 向下 时位置是固定的 但是当浏览器调整大小 向左 向右 时 位置是绝对或相对的 本质上 我想将一个元素放置在距浏览器窗口
  • C#,如何让图片背景透明?

    我有一个图片框 里面有一个png 然而 即使我将背景色设置为透明 它也不是透明的 有什么想法可能是错的吗 Thanks 我也遇到过有关透明图片的问题 你必须通过代码来绘制它 看我的问题图片框问题 EDIT In 绘画事件 包含背景图像的控件
  • 使用迭代器删除对象时出现 IllegalStateException

    我已经被这个错误困扰了一段时间 但我不知道问题出在哪里 我的代码是这样的 ArrayList
  • 使用 Gensim 提取短语时出错

    我正在尝试使用 Gensim 中的短语来获取句子中的二元组 如下所示 from gensim models import Phrases from gensim models phrases import Phraser documents
  • 用 javascript 获取真正的源代码?

    好吧 我对 js 的了解还不够 但是有没有办法用它来获取页面的真正源代码 例如 document body innerHTML 提供了某种 修复 版本 其中格式错误的标签已被删除 我猜想在原始页面上使用 XMLHttpRequest 可能会
  • 按钮背景颜色

    我需要改变background使用 C 代码 Visual Studio 2008 的按钮颜色 我看到有些人建议加入指令 using System Windows Media 我尝试了一下 它触发了此错误 Windows 不存在于names
  • 提取并列出匹配的单元格

    我试图比较包含公司名称的两列 A 和 B 找到任何完全匹配的名称 并将它们列在 C 列中 使用下面的代码 我没有收到错误 但什么也没有发生 如果有人能指出我正确的方向 我将不胜感激 Sub match Dim LastRow As Inte
  • Python——使用 beautifulsoup 抓取“展开”按钮中的内容

    我正在抓取一个黄页来获取一个城市所有物理治疗师的名字 通过该 url 我可以获得 50 名物理治疗师的列表 但是 当我展开页面时 该 url 不会改变 我如何获得完整的名单 这就是我获取罗斯托克市物理治疗师名单的方式 url https w
  • Io 异常:Oracle 云中的 Oracle 错误 ORA-12650

    我一直在为我的数据库计算机 Oracle 11g 使用 Oracle 云 PAAS Linux 服务器 并拥有可以运行所有 Java 应用程序的 Linux 应用程序服务器 假设我有基于 Spring 的 Web 应用程序 可以连接云数据库
  • 如何以编程方式模拟 Flutter 中按钮上的 onTap?

    例如 Update This GestureDetector is embedded inside a third party package that will invoke a series of animation along wit
  • 为什么这段 javascript 代码片段的日志记录为 1? [复制]

    这个问题在这里已经有答案了 在一次采访中 我被要求猜测以下代码片段的输出 var foo 1 function bar foo 10 return function foo bar console log foo 我认为输出将是 10 因为
  • 如何在 iOS 上的 Swift 中使用 Big5 编码

    我正在扫描带有 Big5 编码的汉字的二维码 主页概况 在 Swift 3 中是否有机会正确解码该字符串 我找到了这个Objective C 示例在 GitHub 和这个上那么问题 但是没有kCFStringEncodingBig5 HKS
  • 如何在 Dart 中从 Cloud Firestore 获取随机文档(适用于 Flutter)? [关闭]

    Closed 这个问题需要细节或清晰度 目前不接受答案 Lets say I have the following documents inside a Firestore collection How can I randomly get
  • Angular 4 的核心模块中的服务真的是单例提供的吗?

    我试图理解 Angular 4 中的核心模块和单例服务 官方文档 https angular io guide ngmodule 说了以下几件事 UserService 是一个应用程序范围的单例 你不想要每一个 模块有自己单独的实例 但确实