如何创建没有循环依赖的模块范围服务?

How to Create a Module Scoped Service without Circular Dependencies?

编辑:由于已接受的答案,现在已修复此问题,stackblitz 现在包含工作代码

首先我知道不建议创建模块范围的服务,我只是想知道是否可以这样做。

我已经创建了一个模块、服务和组件。代码如下。

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Fm5Component } from './fm5/fm5.component';


@NgModule({
  declarations: [
    Fm5Component
  ],
  imports: [
    CommonModule
  ]
})
export class FeatureModule5Module { }

import { Component, OnInit } from '@angular/core';
import { Fm5Service } from '../fm5.service';

@Component({
  selector: 'app-fm5',
  templateUrl: './fm5.component.html',
  styleUrls: ['./fm5.component.scss']
})
export class Fm5Component implements OnInit {

  constructor(private fm5Service: Fm5Service) { }

  ngOnInit(): void {
    this.fm5Service.saySomething();
  }

}

import { Injectable } from '@angular/core';
import { FeatureModule5Module } from './feature-module5.module';

@Injectable({
  providedIn: FeatureModule5Module
})
export class Fm5Service {

  constructor() { }

  saySomething(){
    console.log("something");
  }
}

但是,当我尝试 运行 时,出现循环依赖错误。有可能以某种方式解决这个问题吗?

我看到这个问题在这里以各种形式出现了很多,但我仍然none更明智地知道它是否可以完成。

我创建了一个复制错误的 stackblitz: https://stackblitz.com/edit/angular-ivy-tyavuk?file=src/app/feature-module5/fm5/fm5.service.ts

stackblitz 的错误是

这是 Angular/Typescript 的一个已知问题。查看此线程:https://github.com/angular/angular-cli/issues/10170#issuecomment-415758304

Generally, you should use providedIn property to limit it to a non-root module, when you are creating a thrid-party library. Because this feature was introduced for allowing tree shakeable services.

  • 在应用程序中,只有当您打算使用服务时,您才会编写服务。但是在图书馆中,消费者可能会也可能不会消费它。因此,需要tree-shaking.

这是当前创建的循环依赖:

service--[provides itself to]-->module--[declares]-->component--[depends on]-->service。 这可以防止捆绑器 tree-shaking 它。因此 Angular 警告您使用此模式时会出现循环依赖错误。

了解提供商范围 & providedInXYZModule

  • 当您将带有 providedIn 的服务范围 (XYZService) 指定给特定模块时,您是在告诉 Angular -> 嘿Angular,请将此服务实例限制在指定模块。

  • 案例 1:XYZModule 被另一个模块导入。在这种情况下,XYZService 的单个实例将在该模块中共享。因此,该模块中的任何组件都可以注入 XYZService 而不会出现任何循环依赖错误。

  • 情况2:XYZModuleAppModule导入,在这种情况下,您的服务实例将在整个应用程序中共享。即使有任何延迟加载的模块。

  • 案例3:XYZModuleAppModule & Module2分别导入。在这种情况下,Module2 将创建自己的 XYZService 实例。 Module2 内声明的所有组件将不会共享 AppModuleXYZService

    实例

我在这个stackblitz

中创建了场景

在创建应用程序时,使用 @NgModule 中的 providers 数组将服务范围限制到该模块。

@NgModule({
  declarations: [
    Fm5Component
  ],
  imports: [
    CommonModule
  ],
  providers:[Fm5Service]
})
export class FeatureModule5Module { }

不过,如果您想使用 providedIn 语法,请查看此视觉图以了解问题及其使用新模块的解决方案:https://github.com/angular/angular-cli/issues/10170#issuecomment-414270051