我正在尝试通过新的providedIn
属性提供解析服务。
这是我在受保护的模块中使用的翻译解析器:
import { Injectable } from '@angular/core';
import { Observable , pipe } from 'rxjs';
import {map} from "rxjs/operators";
//This is causing: "WARNING in Circular dependency detected:"
import {ProtectedModule} from "../../../protected/protected.module";
import { HttpHandlerService } from '../../http/http-handler.service';
@Injectable({
providedIn: ProtectedModule //Over here (I need the import for this line)
})
export class TranslationsResolverService {
constructor(private _httpHandlerService : HttpHandlerService) { }
resolve(): any {
//Do Something...
}
}
我在受保护的路由模块中声明了翻译解析器服务:
import { NgModule } from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {AuthGuard} from "../core/resolvers/auth/auth.guard";
import {TranslationsResolverService} from "./../core/resolvers/translations/translations-resolver.service";
const routes: Routes = [
{
path : 'app' ,
component: ProtectedComponent,
resolve : {
translations : TranslationsResolverService // <---- Over here - i can't remove that of course
},
canActivate: [AuthGuard],
]
}
];
@NgModule({
imports : [RouterModule.forChild(routes)],
exports : [RouterModule]
})
export class ProtectedRoutingModule { }
由于我在protected.module
中导入({typescript import)translations-resolver.service.ts
以便在providedIn
属性中使用它的事实,警告:已检测到循环依赖项:
path/to/translations-resolver.service.ts ->
protected/protected.module.ts ->
protected/protected-routing.module.ts ->
path to translations-resolver.service.ts
由于providedIn
属性,添加了第二条路径(protected / protected.module.ts)。
我可以通过仅将translationsResolver
作为NgModule provider
(在providers数组中)来解决此问题,但我更喜欢将其作为injectable
的provider。
有解决此问题的建议吗?
答案 0 :(得分:9)
我遇到了同样的问题。事实证明,解决方案是“不要这样做”,正如一位Angular员工在此主题中所解释的:https://github.com/angular/angular-cli/issues/10170#issuecomment-380673276
归结为当我收集时,由根模块提供的服务更容易摇晃。
我和你一样失望。
答案 1 :(得分:7)
这不是Angular依赖问题。
TypeScript编译器尝试解析循环导入时,会生成循环引用。
创建一个名为ProtectedResolversModule
的新模块,并使用providedIn: ProtectedResolversModule
并将解析器移到那里。
现在,您可以将该模块导入ProtectedModule
,并且在加载ProtectedRoutingModule
时不会出现循环依赖项错误。
使用providers
的{{1}}数组。
答案 2 :(得分:1)
我认为Angular的providedIn
语法有点混乱。似乎使很多人感到困惑。例如。看到这两个github线程:
providedIn
语法似乎有两个主要的优点:
providedIn: 'root'
确保仅获得服务的一个实例但是如果只编写库而不是应用,则只需要(1)(因为为什么要包含不需要的服务在应用程序中),并且只需确保不多次导入服务模块就可以避免使用多个服务实例(2)。
使用providedIn
语法的问题是:
providedIn: 'root'
中断了服务与其“所在”(或“带有”)模块之间的链接-因为该服务不了解该模块,而该模块也不了解该服务。这意味着该服务不再真正属于该模块,而将与该模块的任何引用捆绑在一起。反过来,这意味着现在要由服务消费者来确保在使用服务之前,该服务的可注入依赖项(如果有)是可用的,这很容易混淆,而且违反直觉。 / li>
这与Angular官方指南相反,但我的建议是:请勿使用providedIn
,除非您正在编写需要摇摇晃晃的第三方库-使用而不是模块上的旧(未弃用)providers
语法,即:
@NgModule({
providers: [MyService],
})
答案 3 :(得分:0)
从角度/芯线检查forwardRef()功能。它允许引用尚未定义的引用。
import {MyService} from './service';
constructor(@Inject(forwardRef(() => MyService)) public myService: MyService) {
}
答案 4 :(得分:0)
在 Angular9+ 中
你可以使用 providerIn: Any
基本上它就像模块一样工作,但是你不直接使用模块所以没有更多的循环依赖
文档:https://angular.io/api/core/Injectable#options
<块引用>'any' :在每个延迟加载的模块中提供一个唯一的实例,而所有急切加载的模块共享一个实例。
换句话说,它在不同的注入树中。它与您在其他模块中使用的实例不同。
更多参考
<块引用>'Any' 非常有助于确保服务是模块边界内的单例。它是“root”的强大替代方案,可确保各个模块不会相互产生副作用。
https://indepth.dev/posts/1151/a-deep-dive-into-injectable-and-providedin-in-ivy
providerIn 的代码
private injectableDefInScope(def: ɵɵInjectableDef<any>): boolean {
if (!def.providedIn) {
return false;
} else if (typeof def.providedIn === 'string') {
return def.providedIn === 'any' || (def.providedIn === this.scope);
} else {
return this.injectorDefTypes.has(def.providedIn);
}
}