如何创建没有循环依赖的模块范围服务?
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 警告您使用此模式时会出现循环依赖错误。
了解提供商范围 & providedIn
:XYZModule
。
当您将带有 providedIn
的服务范围 (XYZService
) 指定给特定模块时,您是在告诉 Angular -> 嘿Angular,请将此服务实例限制在指定模块。
案例 1:XYZModule
被另一个模块导入。在这种情况下,XYZService
的单个实例将在该模块中共享。因此,该模块中的任何组件都可以注入 XYZService
而不会出现任何循环依赖错误。
情况2:XYZModule
被AppModule
导入,在这种情况下,您的服务实例将在整个应用程序中共享。即使有任何延迟加载的模块。
案例3:XYZModule
被AppModule
& Module2
分别导入。在这种情况下,Module2
将创建自己的 XYZService
实例。 Module2
内声明的所有组件将不会共享 AppModule
的 XYZService
实例
我在这个stackblitz
中创建了场景
在创建应用程序时,使用 @NgModule
中的 providers
数组将服务范围限制到该模块。
@NgModule({
declarations: [
Fm5Component
],
imports: [
CommonModule
],
providers:[Fm5Service]
})
export class FeatureModule5Module { }
不过,如果您想使用 providedIn
语法,请查看此视觉图以了解问题及其使用新模块的解决方案:https://github.com/angular/angular-cli/issues/10170#issuecomment-414270051
编辑:由于已接受的答案,现在已修复此问题,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 警告您使用此模式时会出现循环依赖错误。
了解提供商范围 & providedIn
:XYZModule
。
当您将带有
providedIn
的服务范围 (XYZService
) 指定给特定模块时,您是在告诉 Angular -> 嘿Angular,请将此服务实例限制在指定模块。案例 1:
XYZModule
被另一个模块导入。在这种情况下,XYZService
的单个实例将在该模块中共享。因此,该模块中的任何组件都可以注入XYZService
而不会出现任何循环依赖错误。情况2:
XYZModule
被AppModule
导入,在这种情况下,您的服务实例将在整个应用程序中共享。即使有任何延迟加载的模块。案例3:
实例XYZModule
被AppModule
&Module2
分别导入。在这种情况下,Module2
将创建自己的XYZService
实例。Module2
内声明的所有组件将不会共享AppModule
的XYZService
我在这个stackblitz
中创建了场景在创建应用程序时,使用 @NgModule
中的 providers
数组将服务范围限制到该模块。
@NgModule({
declarations: [
Fm5Component
],
imports: [
CommonModule
],
providers:[Fm5Service]
})
export class FeatureModule5Module { }
不过,如果您想使用 providedIn
语法,请查看此视觉图以了解问题及其使用新模块的解决方案:https://github.com/angular/angular-cli/issues/10170#issuecomment-414270051