Angular 6 - 提供在非根模块中导致循环依赖

Rtm*_*tmY 28 typescript angular angular6 angular7

我正在尝试通过新的"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...
    }
}
Run Code Online (Sandbox Code Playgroud)

我在受保护的路由模块中声明了翻译解析器服务:

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 { }
Run Code Online (Sandbox Code Playgroud)

由于我在translations-resolver.service.ts 导入(typescript import)protected.module 以便在providedIn属性中使用它,因此我在检测到循环依赖项时获得了警告:

翻译的路径-resolver.service.ts - >

protected/protected.module.ts - >

protected/protected-routing.module.ts - >

翻译的路径 - resolver.service.ts

由于"providedIn"属性,添加了第二条路径(已标记).

我可以通过提供translationsResolver作为NgModule提供程序(在providers数组中)来解决这个问题,但我更喜欢它是一个可注入的提供程序.

有什么建议解决这个问题?

Dar*_*ron 14

我遇到了同样的问题.事实证明解决方案是"不要这样做",正如Angular中的一个人在这个帖子中解释的那样:https://github.com/angular/angular-cli/issues/10170#issuecomment-380673276

当我收集时,它归结为根服务模块提供的服务更易于树摇动.

我和你一样失望.

  • 无论如何,这是一个糟糕的答案:-) (2认同)

Rea*_*lar 12

这不是Angular依赖问题。

循环引用由TypeScript编译器在尝试解析循环导入时生成

第一个解决方案

创建一个名为的新模块,ProtectedResolversModule然后在其中使用providedIn: ProtectedResolversModule和移动解析器。

现在,您可以将该模块导入其中,ProtectedModule并且在加载时不会出现循环依赖项错误ProtectedRoutingModule

第二解决方案

使用的providers数组ProtectedModule

  • 第二种解决方案使其无法进行treeshakable (9认同)
  • 我没有第一个解决方案,请您显示一些代码。 (4认同)

Dan*_*ing 6

我认为Angular的providedIn语法有点混乱。似乎使很多人感到困惑。例如,请参见以下两个github线程:

providedIn语法似乎有两个主要的优点

  1. 它支持未使用服务的摇动
  2. providedIn: 'root' 确保您只能获得一个服务实例

但是,如果只编写而不是应用程序,则只需要(1)(因为为什么要在应用程序中包含不需要的服务),并且可以避免多个服务实例(2)确保您不会多次导入服务模块。

问题providedIn语法是:

  1. providedIn: 'root'断开服务与它“驻留”(或带有)的模块之间的链接-因为服务不了解模块,模块也不了解服务。这意味着该服务不再真正属于该模块,而将与该模块的任何引用捆绑在一起。反过来,这意味着服务使用者现在必须确保在使用服务之前可以使用该服务的可注入依赖项(如果有的话),这会造成混淆并且很违反直觉。
  2. 上述循环参考问题。如果该服务实际上被同一模块内的任何组件使用,则实际上不可能(通过这种语法)保留服务及其模块之间的链接。

这与Angular官方指南相反,但是我的建议是:不要使用providedIn,除非您正在编写需要摇摇树的第三方库 - providers而是在模块上使用旧的(未弃用的)语法,即:

@NgModule({ providers: [MyService], })

附录

现在,我已经收到5票赞成票,因此,我觉得我应该保持冷静,说我不再真正遵循我的建议了!

由于使用了官方的(并且广为遵循的)Angular策略providedIn: 'root',因此我决定,如果我坚持这一点,那么总体上来说,对于其他开发人员来说,它不会造成混淆。到目前为止,它还没有给我造成任何问题,但是上面的警告仍然存在,我相信重要的是要意识到这一点。

  • 您应该将附录放在答案的顶部,例如“2019 年 10 月更新”,以便人们在您的旧答案之前先阅读它。(节省不必要的阅读和混乱) (4认同)