typescript Angular 6+ :ProvidedIn 非根模块导致循环依赖
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/51062235/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular 6+ :ProvidedIn a non root module is causing a circular dependency
提问by RtmY
I'm trying to provide a resolve service via the new providedIn
attribute.
我正在尝试通过新providedIn
属性提供解析服务。
This is a translations resolver which I use in a protected module:
这是我在受保护模块中使用的翻译解析器:
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...
}
}
I declared the translations resolver service in the protected routing module:
我在受保护的路由模块中声明了翻译解析器服务:
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 { }
Because of the fact that I import (typescript import) the protected.module
in the translations-resolver.service.ts
in order to use it in the providedIn
attributeI get a WARNING in Circular dependency detected:
因为事实上,我进口(进口打字稿)的protected.module
中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
The 2nd path (protected/protected.module.ts) is added due to the providedIn
attribute.
由于该providedIn
属性,添加了第二个路径(protected/protected.module.ts)。
I can fix this by just providing the translationsResolver
as a NgModule provider
(in the providers array) but I prefer it to be an injectable
provider.
我可以通过提供translationsResolver
as a NgModule provider
(在 providers 数组中)来解决这个问题,但我更喜欢它是一个injectable
提供者。
Any suggestions for solving this?
有什么建议可以解决这个问题吗?
采纳答案by Reactgular
This isn't an Angular dependencies problem.
这不是 Angular 依赖问题。
The circular reference is generated by the TypeScript compiler when it tries to resolve the circular imports.
循环引用由 TypeScript 编译器在尝试解析循环导入时生成。
First Solution
第一个解决方案
Create a new module named ProtectedResolversModule
and use providedIn: ProtectedResolversModule
and move the resolvers there.
创建一个名为的新模块ProtectedResolversModule
,providedIn: ProtectedResolversModule
并在那里使用和移动解析器。
Now you can import that module into ProtectedModule
and you won't get a circular dependency error when loading ProtectedRoutingModule
.
现在您可以将该模块导入,ProtectedModule
并且在加载ProtectedRoutingModule
.
Second Solution
第二种解决方案
Use the providers
array of ProtectedModule
.
使用providers
数组ProtectedModule
。
回答by DarkNeuron
I ran into the same problem. Turns out the solution is "don't do it", as explained in this thread by one of the Angular guys: https://github.com/angular/angular-cli/issues/10170#issuecomment-380673276
我遇到了同样的问题。事实证明,解决方案是“不要这样做”,正如其中一位 Angular 人员在此线程中所解释的那样:https: //github.com/angular/angular-cli/issues/10170#issuecomment-380673276
It boils down to services being easier to tree shake when they are provided by the root module, as I gather.
正如我所收集的,这归结为当根模块提供服务时更容易进行树形摇晃。
I'm as disappointed as you are.
我和你一样失望。
回答by Dan King
Update - Oct 2019
更新 - 2019 年 10 月
I've received 5 up-votes now for this answer, so I feel as though I ought to come clean and say that I'm no longer actually following my own advice on this (below)!
我现在已经收到了 5 票赞成这个答案,所以我觉得我应该坦率地说我实际上不再遵循我自己的建议(如下)!
Since official (and widely followed) Angular policy is to use providedIn: 'root'
, I decided that on the whole it would be less confusing for other developers if I just stuck with this. So far it hasn't caused me any problems, but the caveats below still remain and I believe it's important to remain aware of this.
由于官方(并广泛遵循)的 Angular 政策是使用providedIn: 'root'
,我决定总的来说,如果我坚持这一点,其他开发人员就不会那么困惑。到目前为止,它还没有给我带来任何问题,但下面的警告仍然存在,我相信保持意识到这一点很重要。
Original Post
原帖
I think Angular have made a bit of a mess of the providedIn
syntax. It seems to have confused a lot of people. E.g. see these two github threads:
我认为 Angular 的providedIn
语法有点混乱。好像把很多人搞糊涂了。例如,查看这两个 github 线程:
The providedIn
syntax seems to have 2 main benefits:
该providedIn
语法似乎有两个主要的优点:
- It supports tree-shaking of unused services
providedIn: 'root'
ensures that you only ever get one instance of the service
- 它支持对未使用的服务进行摇树
providedIn: 'root'
确保您只获得一个服务实例
But you only really need (1) if you're writing a libraryrather than an application(because why would you include a service that you didn't need in your application), and you can avoid multiple service instances (2) just by making sure you don't import the service module more than once.
但是,如果您正在编写库而不是应用程序(因为为什么要在应用程序中包含您不需要的服务),那么您只需要(1),并且您可以避免多个服务实例(2)确保您不会多次导入服务模块。
The problemswith the providedIn
syntax are:
该问题与providedIn
语法是:
providedIn: 'root'
breaks the link between the service and the module it "lives in" (or "with") - because the service doesn't know about the module and the module doesn't know about the service. This means the service no longer really "belongs" to that module, and will just get bundled with whatever references it. This in turn means that it is now up to the service consumerto make sure the service's injectable dependencies (if it has any) are available before it is used, which is confusing and quite counter-intuitive.- The circular reference problem described above. It is actually not possible- via this syntax - for the link between the service and its module to be preserved, if the service is actually used by any components within the same module.
providedIn: 'root'
断开服务与其“所在”(或“与之共存”)的模块之间的链接——因为服务不知道模块,模块也不知道服务。这意味着该服务不再真正“属于”该模块,而只会与引用它的任何内容捆绑在一起。这反过来意味着现在由服务使用者来确保服务的可注入依赖项(如果有的话)在使用之前可用,这很容易混淆并且非常违反直觉。- 上面描述的循环引用问题。如果服务实际上被同一模块内的任何组件使用,则实际上不可能- 通过此语法 - 保留服务与其模块之间的链接。
This is contrary to official Angular guidance, but my advice would be: Don't use providedIn
, unless you are writing a third party library which requires tree-shaking- use the old (not deprecated) providers
syntax on the module instead, i.e.:
这与官方的 Angular 指南相反,但我的建议是:不要使用providedIn
,除非您正在编写需要摇树的第三方库- 请改用providers
模块上的旧(未弃用)语法,即:
@NgModule({
providers: [MyService],
})
@NgModule({
providers: [MyService],
})
回答by Ozgur
Check forwardRef()function from angular/core. It allows to refer to references which are not yet defined.
从 angular/core检查forwardRef()函数。它允许引用尚未定义的引用。
import {MyService} from './service';
constructor(@Inject(forwardRef(() => MyService)) public myService: MyService) {
}