2016-07-17 149 views
7

Quali sono gli usi del provider useExisting?Angular 2 use Fornitori esistenti

È useExistingOrThrowIfThereIsNone o useExistingOrCreateIfThereIsNone? Uno di questi comportamenti può essere scelto di proposito in qualche modo, a seconda delle nostre esigenze? Se uno di essi non è supportato, è possibile emulare uno non supportato?

La documentazione non è chiara su questo e basta dare un esempio che useExisting può riutilizzare un'istanza da useClass.

risposta

14

Con questo esempio

providers: [ 
    A, 
    {provide: B, useClass: A}, 
    {provide: C, useExisting: A}] 

Se hai

constructor(private a: A) 

un'istanza per il primo provider è stato creato.

constructor(private b: B) 

un'istanza per il 2 ° fornitore è creato

constructor(private c: C) 

l'istanza del primo fornitore viene iniettato.

Se si inizia fresco con

constructor(private c: C) 

un'istanza per il primo fornitore è creato e iniettato

+0

Quindi, è "useExistingOrCreateIfThereIsNone'. E userà l'istanza esistente dall'iniettore genitore. E il possibile caso d'uso per useExisting è quando vogliamo mantenere una singola istanza di provider per l'intera app (ad esempio 'Http' che potrebbe essere derisa per l'intera app), non è vero? – estus

+0

'useExisting' è come un alias per un altro provider. 'useClass' è solo un nuovo provider che mappa dal tipo richiesto al tipo effettivo ma la chiave è il tipo richiesto. –

+0

Ok, quindi dovrebbe essere un fornitore diverso, non possiamo semplicemente fare '{provider: Service, useExisting: Service}' per rendere 'Service' un singleton ovunque. – estus

2

Quando scriviamo {provide: A, useClass: B}, angolare creerà mappa tra gettoneA e classeB.

Quando scriviamo {provide: A, useExisting: B}, angolare creerà mappa tra gettoneA e gettoneB.

differenza tra queste mappe:

  • di token A -> istanza della classe B
  • di token A -> Token B -> istanza di una classe per il token di B
1

Proprio piccola aggiunta/chiarimento alla risposta di @ GünterZöchbauer.

In realtà utilizzaExistingOrThrowIfThereIsNone quando si tratta di token . useExisting crea un alias in un altro token, non un'istanza , quindi lo deve essere il token indicato da useExisting, altrimenti verrà generata un'eccezione. Ma quando stiamo parlando delle istanze , funzionerà fino a quando l'ultimo token nella catena registra l'istanza , quindi in questo senso è useExistingOrCreateIfThereIsNone.

Considerate questo:

// T = token, I = instance 
providers: [ 
    {provide: B, useClass: A}, // T[B] => I[A] 
    {provide: C, useExisting: A}] // T[C] => ??? - there's no T[A] declared 

... 
constructor(private a: B) {} // works 
... 
constructor(private a: C) {} // throws an exception: 

In questo caso seconda dichiarazione genera un errore perché gettone C si riferisce a gettone A ma non c'è gettone A dichiarata in qualsiasi punto, anche se c'è un istanza di classe A nell'iniettore. Angolare non tenterà di creare esempio A per gettone C o associato gettone C con esistente esempio A. Ho appena accidentalmente verificato in uno dei miei progetti. :)

Quanto segue funzionerà anche se per ragioni ben descritto in altre risposte:

providers: [ 
    {provide: B, useClass: A}, // T[B] => I[A] 
    {provide: C, useExisting: B}] // T[C] => T[B] => I[A] 

... 

constructor(private a: B) {} // works 
... 
constructor(private a: C) {} // works 

In questo esempio istanza di A verrà creata per gettone C anche se non vi era alcuna istanza Un creato in precedenza per gettone B. Così, per gettone C è "usare qualsiasi esempio opportuno prevedere token B "e per il token B" utilizzare "esistente istanza A o creare nuovo se non ce n'è".

+0

Questo è un buon punto. Per quanto mi riguarda, è ovvio che i fornitori sono risolti in base ai loro token, non ai valori. – estus