web-dev-qa-db-fra.com

Angular 6: fournissez HTTP_INTERCEPTORS pour 'root'

Avec le changement de Angular 5 où vous fournissez un service dans AppModule à Angular 6 où vous définissez la clé 'supplyIn' dans @Injectable decorator, j'ai modifié tous les services pour utiliser la nouvelle méthode "supplyIn". Cependant, l'exception est mon service d'intercepteur.

Comment puis-je fournir le jeton HTTP_INTERCEPTORS pour 'root' et utiliser InterceptorService?

c'est la façon angulaire 5 que j'utilise atm:

@Injectable()
export class InterceptorService implements HttpInterceptor {
...
}

dans AppModule:

providers: [{
  provide: HTTP_INTERCEPTORS,
  useClass: InterceptorService,
  multi: true
}]

Mais quelle serait la manière angulaire 6?

J'ai essayé quelque chose comme

@Injectable({
  provideIn: 'root',
  useValue: HTTP_INTERCEPTORS,
  deps: [forwardRef(() => InterceptorService)]
})
export class InterceptorService implements HttpInterceptor {
...
}

et beaucoup d’autres variantes avec Injectable, mais il semble impossible de comprendre comment le faire fonctionner sans écrire un littéral d’objet directement dans les fournisseurs d’un module.

6
Miloš Tomšik

La propriété provideIn- de Angular 6 n'est qu'un ajout au comportement de Angular 5. Si vous souhaitez fournir quelque chose avec un InjectionToken existant, vous devez toujours utiliser la syntaxe { provide: ClassA, useClass: ClassB }.

Voir -> https://angular.io/guide/dependency-injection-in-action#external-module-configuration

tl; dr: La façon dont vous fournissez HTTP_INTERCEPTORS n’a pas changé dans Angular 6 et il n’existe pas de voie "Angular 6".

4
Leon

Dans l'intercepteur

@Injectable()
export class InterceptorService implements HttpInterceptor {
...
}

Dans le module d'application

providers: [{
  provide: HTTP_INTERCEPTORS,
  useClass: InterceptorService,
  multi: true
}]

"providedIn ... indique à Angular que l'injecteur racine est responsable de créer une instance du [service]. Les services fournis de cette manière sont> automatiquement mis à la disposition de l'application entière et ne doivent pas nécessairement l'être énumérés dans n’importe quel module. "

"Si un fournisseur ne peut pas être configuré dans le décorateur @Injectable du service , Enregistrez les fournisseurs au niveau de l'application dans le AppModule racine, pas Dans le AppComponent. Généralement, enregistrez les fournisseurs dans le NgModule plutôt que> dans le> composant d'application racine. "

En outre, si la portée du service doit être limitée à une fonctionnalité ou à une branche de l'application, fournissez ce service au composant de niveau supérieur pour cette branche/fonctionnalité.

https://angular.io/guide/dependency-injection-in-action

1
Ian Flynn

Quelques choses à noter ici:

1. providedIn: 'root' est une fonctionnalité intéressante, mais elle n'a probablement pas été conçue pour vous

Comme @Leon l'a mentionné, cette fonctionnalité vise à rendre les services plus faciles à manipuler. Il n'est pas destiné à remplacer complètement l'utilisation de la propriété providers: [] d'un module. C'est une option principalement destinée aux développeurs de bibliothèques, pas autant aux développeurs d'applications.

Imaginez ce scénario:

Vous avez créé un service il y a quelques mois et votre application ne l'utilise plus. Vous savez qu'il ne l'utilise pas parce que c'est votre application et que vous avez la connaissance et le contrôle total de la base de code. Que faites-vous à ce service?

A) Assurez-vous qu'il utilise providedIn: 'root' pour que Angular puisse le faire sortir du paquet puisque vous ne l'utilisez plus.

B) Supprimer le service.

Je suppose que c'est B!

Imaginez un autre scénario:

Vous utilisez un module angulaire tiers issu d'un package npm. Ce module contient 12 services différents que vous pouvez utiliser dans votre application pour tirer parti de ses fonctionnalités. Votre application n'a pas besoin de toutes ces fonctionnalités, vous n'injectez donc que 3 de ces types de service dans vos composants ou services d'application.

Comment résolvez-vous cela?

A) Branchez le référentiel afin de pouvoir supprimer tous les services que votre application n'utilise pas afin de ne pas avoir à les inclure dans votre bundle.

B) Demandez au propriétaire du projet d'utiliser providedIn: 'root'. Si l'auteur de la bibliothèque a utilisé providedIn: 'root', les services que vous n'utilisez pas n'ont pas d'incidence sur la taille de votre paquet et peuvent rester dans le package npm/module Angular pour que les autres équipes puissent les utiliser s'ils en ont besoin.

Je suppose que c'est B!

2. providedIn: 'root' ne fonctionne pas pour les intercepteurs

Les intercepteurs sont un service de jeton ID multi, ce qui signifie que vous pouvez fournir plusieurs valeurs pour le même jeton ID. Ce jeton est HTTP_INTERCEPTORS. Le décorateur @Injectable({...}) n'expose aucune API pour fournir le type décoré d'un jeton différent de celui utilisé par le décorateur @NgModule({...}).

Cela signifie que vous ne pouvez pas indiquer Anywhere you would normally ask for 'HTTP_INTERCEPTORS' add this service to the set of values to use instead angulaire à l'aide du décorateur @Injectable({...}).

Vous ne pouvez le faire que dans un décorateur @NgModule({...}).

3. La fourniture d'intercepteurs dépend de l'ordre

Les intercepteurs sont un pipeline et l'ordre dans lequel ils sont fournis pour déterminer l'ordre dans lequel ils ont accès à l'objet de requête (modifier ou inspecter) et à l'objet de réponse (modifier ou inspecter).

Bien que certains intercepteurs puissent être agnostiques dans l’ordre, vous voulez probablement encore un certain déterminisme dans cet ordre.

Ainsi, même si providedIn: 'root' fonctionnait pour les intercepteurs, l'ordre dans lequel ils seraient fournis serait déterminé par l'ordre de résolution des types lors de la compilation angulaire - probablement pas ce que vous voulez.

Au lieu de les fournir dans le tableau providers: [] dans un décorateur @NgModule({...}), vous pouvez définir explicitement l'ordre dans lequel ils seront appelés.

0
seangwright