web-dev-qa-db-ja.com

Angular 6+:ProvidedIn非ルートモジュールが循環依存関係を引き起こしている

新しい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内のtranslations-resolver.service.tsをインポート(TypeScriptインポート)するため、providedIn属性で使用するためで警告が表示されます循環依存が検出されました:

path/to/translations-resolver.service.ts -> 

protected/protected.module.ts ->

protected/protected-routing.module.ts -> 

path to translations-resolver.service.ts

providedIn属性により、2番目のパス(protected/protected.module.ts)が追加されます。

translationsResolverNgModule provider(providers配列内)として提供することでこれを修正できますが、injectableプロバイダーであることが望ましいです。

これを解決するための提案はありますか?

22
Rotemya

これはAngular依存関係の問題ではありません。

循環参照は、循環importsを解決しようとするときにTypeScriptコンパイラーによって生成されます。

最初の解決策

ProtectedResolversModuleという名前の新しいモジュールを作成し、providedIn: ProtectedResolversModuleを使用してリゾルバーをそこに移動します。

これで、そのモジュールをProtectedModuleにインポートできるようになり、ProtectedRoutingModuleをロードするときに循環依存エラーが発生しなくなりました。

第二の解決策

providersProtectedModule配列を使用します。

9
Reactgular

私は同じ問題に遭遇しました。 Angular guys: https://github.com/angular/angular- cli/issues/10170#issuecomment-380673276

まとめると、ルートモジュールによって提供されるサービスは、ツリーシェークが簡単になるということになります。

私はあなたと同じくらい失望しています。

13
DarkNeuron

AngularはprovidedIn構文を少し混乱させました。多くの人を混乱させたようです。たとえば、次の2つのgithubスレッドを参照してください。

providedIn構文には、2つのメイン利点があるようです:

  1. 未使用のサービスのツリーシェーキングをサポートします
  2. _providedIn: 'root'_は、サービスのインスタンスを1つだけ取得することを保証します

ただし、本当に必要なのは(1)applicationではなくlibraryを記述する場合のみです(アプリケーションに不要なサービスを含める理由が理由です) )、およびサービスモジュールを複数回インポートしないようにするだけで、複数のサービスインスタンス(2)を回避できます。

providedIn構文のproblemsは次のとおりです。

  1. _providedIn: 'root'_は、サービスとそれが「ライブ」(または「with」)するモジュールとの間のリンクを解除します-サービスはモジュールを知らず、モジュールはサービスを知らないからです。これは、サービスがそのモジュールに実際に「属する」ことはなく、それを参照するものとバンドルされることを意味します。これは、サービスの注入可能な依存関係(ある場合)が使用される前に利用できるようにするためにサービスconsumerになったことを意味します。これは混乱し、直観に反します。
  2. 上記の循環参照の問題。実際にはpossible-この構文を介して-サービスとそのモジュール間のリンクを保持するために、同じモジュール内のコンポーネントが実際にサービスを使用している場合

これは公式のAngularガイダンスに反していますが、私のアドバイスは次のようになります:providedInを使用しないでください。 tree-shakingが必要です-モジュールの古い(非推奨ではない)providers構文を代わりに使用してください。つまり:

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

4
Dan King

forwardRef() 角度/コアからの関数を確認してください。まだ定義されていない参照を参照できます。

import {MyService} from './service';

constructor(@Inject(forwardRef(() => MyService)) public myService: MyService) {
}
0
Ozgur