web-dev-qa-db-fra.com

Angular 6+: FourniDans un module autre que root provoque une dépendance circulaire

J'essaie de fournir un service de résolution via le nouvel attribut providedIn.

C'est un résolveur de traduction que j'utilise dans un module protégé:

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...
    }
}

J'ai déclaré le service de résolution de traductions dans le module de routage protégé:

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 { }

A cause du fait que j'importe (import TypeScript) le protected.module dans le translations-resolver.service.tsafin de l'utiliser dans l'attribut providedIn Je reçois un AVERTISSEMENT dans une dépendance circulaire détectée:

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

protected/protected.module.ts ->

protected/protected-routing.module.ts -> 

path to translations-resolver.service.ts

Le deuxième chemin (protected/protected.module.ts) est ajouté en raison de l'attribut providedIn.

Je peux résoudre ce problème en fournissant simplement le translationsResolver en tant que NgModule provider (dans le tableau providers) mais je préfère que ce soit un fournisseur injectable.

Des suggestions pour résoudre ceci?

22
Rotemya

Ce n'est pas un problème de dépendances Angular).

La référence circulaire est générée par le compilateur TypeScript lorsqu'il tente de résoudre la circulaire imports.

Première solution

Créez un nouveau module nommé ProtectedResolversModule et utilisez providedIn: ProtectedResolversModule et déplacez les résolveurs à cet endroit.

Vous pouvez maintenant importer ce module dans ProtectedModule et vous ne recevrez pas d'erreur de dépendance circulaire lors du chargement de ProtectedRoutingModule.

Deuxième solution

Utilisez le tableau providers de ProtectedModule.

9
Reactgular

J'ai rencontré le même problème. Il s'avère que la solution est "ne le fais pas", comme expliqué dans ce fil par l'un des Angular gars: https://github.com/angular/angular- cli/issues/10170 # issuecomment-380673276

Cela revient à dire que les services sont plus faciles à manipuler lorsqu'ils sont fournis par le module racine, si je comprends bien.

Je suis aussi déçu que toi.

13
DarkNeuron

Je pense que Angular a un peu gâché la syntaxe providedIn. Il semble avoir dérouté beaucoup de gens. Par exemple, voyez ces deux threads github:

La syntaxe providedIn semble avoir 2 avantages principaux :

  1. Il prend en charge l’arborescence des services inutilisés
  2. providedIn: 'root' Vous garantit de ne recevoir qu'une seule instance du service.

Mais vous n’avez vraiment besoin que (1) si vous écrivez une bibliothèque plutôt que application (car pourquoi voudriez-vous inclure un service que vous n’avez pas utilisé? votre application), et vous pouvez éviter plusieurs instances de service (2) simplement en vous assurant de ne pas importer le module de service plus d’une fois.

Les problèmes avec la syntaxe providedIn sont les suivants:

  1. providedIn: 'root' Rompt le lien entre le service et le module dans lequel il "vit" (ou "avec") - car le service ne connaît pas le module et le module ne le sait pas. Cela signifie que le service n'appartient plus vraiment à ce module et sera simplement groupé avec les références qui le concernent. Cela signifie à son tour qu'il incombe maintenant au service consommateur de s'assurer que les dépendances injectables du service (le cas échéant) sont disponibles avant son utilisation, ce qui est déroutant et plutôt contre-intuitif. .
  2. Le problème de référence circulaire décrit ci-dessus. En fait, ce n'est pas possible - via cette syntaxe - pour que le lien entre le service et son module soit préservé, si le service est réellement utilisé par des composants du même module.

Ceci est contraire aux instructions officielles Angular, mais mon conseil serait: N'utilisez pas providedIn, sauf si vous écrivez une tierce partie. bibliothèque qui nécessite une arborescence - utilise l'ancienne syntaxe _ ($ obsolète) providers du module, c'est-à-dire:

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

4
Dan King

Vérifier forwardRef () fonction de angular/core. Cela permet de faire référence à des références qui ne sont pas encore définies.

import {MyService} from './service';

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