Quel est le but de providedIn avec le décorateur injectable lors de la génération de services dans Angular 6?

136

Lors de la génération de services dans la CLI angulaire, il ajoute des métadonnées supplémentaires avec une propriété «fourni dans» avec une valeur par défaut «racine» pour le décorateur injectable.

@Injectable({
  providedIn: 'root',
})

Que fait exactement fourniIn? Je suppose que cela rend le service disponible comme un service singleton de type `` global '' pour toute l'application, cependant, ne serait-il pas plus propre de déclarer de tels services dans le tableau de fournisseurs de l'AppModule?

METTRE À JOUR:

Pour n'importe qui d'autre, le paragraphe suivant en a également fourni une autre bonne explication, en particulier si vous souhaitez fournir votre service uniquement à un module fonctionnel.

Il existe maintenant un nouveau moyen recommandé pour enregistrer un fournisseur, directement dans le @Injectable()décorateur, en utilisant le nouvel providedIn attribut. Il accepte 'root'comme valeur ou tout module de votre application. Lorsque vous utilisez 'root', votre injectablesera enregistré en tant que singleton dans l'application, et vous n'avez pas besoin de l'ajouter aux fournisseurs du module racine. De même, si vous utilisez providedIn: UsersModule, le injectableest enregistré comme fournisseur du UsersModulesans l'ajouter au providersmodule. "- https://blog.ninja-squad.com/2018/05/04/what-is-new-angular -6 /

MISE À JOUR 2:

Après une enquête plus approfondie, j'ai décidé qu'il était seulement utile d'avoir providedIn: 'root'

Si vous voulez provideun service dans un module autre que le module racine, il vaut mieux utiliser le providerstableau dans les décorateurs du module de fonctionnalités, sinon vous serez en proie à des dépendances circulaires. Des discussions intéressantes à avoir ici - https://github.com/angular/angular-cli/issues/10170

Stefan Zvonar
la source
17
Je pense que vos mises à jour devraient être une réponse (vous pouvez répondre à vos propres questions) au lieu de l'ajouter à votre question.
PhoneixS
La partie la plus importante est SINGLETON, personne ne le mentionne!
Kyle Burkett

Réponses:

54

si vous utilisez providedIn, l'injectable est enregistré en tant que fournisseur du module sans l'ajouter aux fournisseurs du module.

De Docs

Le service lui-même est une classe générée par la CLI et décorée avec @Injectable. Par défaut, ce décorateur est configuré avec une propriété providedIn, qui crée un fournisseur pour le service. Dans ce cas, providedIn: 'root' spécifie que le service doit être fourni dans l'injecteur racine.

Sajeetharan
la source
4
Merci Sajeetharan. D'accord, on dirait donc que c'est un nouveau moyen de raccourci pour spécifier où le service doit être fourni. Je suppose que ma préférence initiale aurait été de regarder la liste des fournisseurs d'un module pour voir tous les services déclarés comme fournisseurs, plutôt que de parcourir la base de code dispersée pour les balises ProvidedIn .... (?)
Stefan Zvonar
2
Y avait-il une raison pour Angular d'ajouter cela? Y a-t-il un problème que cela résout? Je ne vois pas de raison à cela.
prolink007
3
Garde la définition AppModule / CoreModule un peu plus petite;)
Stefan Zvonar
22
@ prolink007. L'utilisation de providedIn permet aux services d'être chargés paresseusement par l'application. Pour tester cela, placez les journaux de la console dans vos services. Ma page d'accueil chargeait 16 services, maintenant elle en charge 9. Il est difficile de quantifier les performances, mais je me sens mieux en sachant que je ne charge pas les services avant d'en avoir besoin :).
Stevethemacguy
3
Vous pouvez rendre vos services modifiables dans l'arborescence en utilisant l' providedInattribut pour définir où le service doit être initialisé lors de l'utilisation du @Injectable()décorateur. Ensuite, vous devez le supprimer de l'attribut provider de votre NgModuledéclaration ainsi que de sa déclaration d'importation. Cela peut aider à réduire la taille du bundle en supprimant le code inutilisé du bundle.
nircraft
48

providedIn: 'root' est le moyen le plus simple et le plus efficace de fournir des services depuis Angular 6:

  1. Le service sera disponible à l'échelle de l'application en tant que singleton sans avoir besoin de l'ajouter au tableau de fournisseurs d'un module (comme Angular <= 5).
  2. Si le service n'est utilisé que dans un module chargé différé, il sera chargé différé avec ce module
  3. S'il n'est jamais utilisé, il ne sera pas contenu dans la construction (arbre secoué).

Pour plus d'informations, consultez la documentation et les FAQ de NgModule

Btw:

  1. Si vous ne voulez pas de singleton à l'échelle de l'application, utilisez plutôt le tableau d'un composant du fournisseur.
  2. Si vous souhaitez limiter la portée afin qu'aucun autre développeur n'utilise jamais votre service en dehors d'un module particulier, utilisez providersplutôt le tableau de NgModule.
Mick
la source
38

Depuis Docs

Qu'est-ce que le décorateur injectable?

Marque une classe comme disponible pour l'injecteur pour la création.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class UserService {
}

Le service lui-même est une classe générée par la CLI et décorée avec @Injectable ().

Que fait exactement fourniIn?

Détermine quels injecteurs fourniront l'injectable, soit en l'associant à un @NgModule ou à un autre InjectorType, soit en spécifiant que cet injectable doit être fourni dans l'injecteur `` racine '', qui sera l'injecteur au niveau de l'application dans la plupart des applications.

providedIn: Type<any> | 'root' | null

providedIn: 'racine'

Lorsque vous fournissez le service au niveau racine, Angular crée une seule instance de service partagée et l'injecte dans n'importe quelle classe qui le demande. L'enregistrement du fournisseur dans les métadonnées @Injectable () permet également à Angular d'optimiser une application en supprimant le service de l'application compilée s'il n'est pas utilisé.

fourniDans: Module

Il est également possible de spécifier qu'un service doit être fourni dans un @NgModule particulier. Par exemple, si vous ne souhaitez pas qu'un service soit disponible pour les applications à moins qu'elles n'importent un module que vous avez créé, vous pouvez spécifier que le service doit être fourni dans le module

import { Injectable } from '@angular/core';
import { UserModule } from './user.module';

@Injectable({
  providedIn: UserModule,
})
export class UserService {
}

Cette méthode est préférée car elle permet la secousse d' arbre (la secousse d' arbre est une étape d'un processus de construction qui supprime le code inutilisé d'une base de code ) du service si rien ne l'injecte.

S'il n'est pas possible de spécifier dans le service quel module doit le fournir, vous pouvez également déclarer un fournisseur pour le service dans le module:

import { NgModule } from '@angular/core';
import { UserService } from './user.service';

@NgModule({
  providers: [UserService],
})
export class UserModule {
}
Nipuna
la source
4
La meilleure explication.
nop
2
cette réponse est meilleure que la définition dans angular doc. très clair.
Shameera Anuranga
2
Très bien expliqué, merci beaucoup!
Zaki Mohammed
Et quand c'est vide, par exemple @Injectable()?
Ben Taliadoros le
13

providedIn indique à Angular que l'injecteur racine est responsable de la création d'une instance de votre service. Les services fournis de cette manière sont automatiquement mis à la disposition de l'ensemble de l'application et n'ont pas besoin d'être répertoriés dans aucun module.

Les classes de service peuvent agir comme leurs propres fournisseurs, c'est pourquoi les définir dans le décorateur @Injectable est tout l'enregistrement dont vous avez besoin.

Jawad Farooqi
la source
4

Selon le Documentation:

L'enregistrement du fournisseur dans les métadonnées @Injectable () permet également à Angular d'optimiser une application en supprimant le service de l'application compilée s'il n'est pas utilisé.

Maarti
la source