Angular2: 2 servizi dipendenti l’uno dall’altro

nella mia app Angular 2 ho due servizi che dipendono l’uno dall’altro (Servizio A metodi di chiamata dal Servizio B e viceversa). Ecco i codici pertinenti: In app.component.ts:

import {Component} from 'angular2/core'; import {TempService} from '../services/tmp'; import {Temp2Service} from '../services/tmp2'; @Component({ selector: 'my-app', templateUrl: 'app/app/app.component.html', providers: [TempService, Temp2Service] }) export class AppComponent { (...) } 

Servizio 1:

 import {Injectable} from 'angular2/core'; import {Temp2Service} from './tmp2'; @Injectable() export class TempService { constructor (private _sessionService: Temp2Service) {} } 

Servizio 2:

 import {Injectable} from 'angular2/core'; import {TempService} from './tmp'; @Injectable() export class Temp2Service { constructor (private _sessionService: TempService) {} } 

L’esecuzione dell’app porta al seguente errore:

ECCEZIONE: imansible risolvere tutti i parametri per “Temp2Service” (non definito). Assicurati che tutti i parametri siano decorati con Inject o abbiano annotazioni di tipo valide e che ‘Temp2Service’ sia decorato con Injectable

Quando si commenta il costruttore in uno dei servizi, l’app funziona correttamente. Quindi la mia ipotesi è che il “riferimento incrociato” dei due servizi sta causando il problema. Hai un’idea di cosa sta andando storto qui? O il mio approccio è già sbagliato?

Grazie per i vostri suggerimenti!

Questa è una dipendenza circolare chiamata. Non è un problema con Angular2 stesso. Non è permesso in nessuna lingua di cui sono a conoscenza.

Dovrai rifattorizzare il tuo codice per rimuovere questa dipendenza circolare. Probabilmente avrai bisogno di suddividere uno di questi servizi in un nuovo servizio.

Seguendo il principio del singolo responsabile, scoprirai che non entrerai nella trappola della dipendenza circolare.

L’iniezione del costruttore impedisce le dipendenze circolari.

Può essere scomposto iniettando l’ Injector e richiedendo una dipendenza in modo imperativo come:

 private payrollService:PayrollService; constructor(/*private payrollService:PayrollService*/ injector:Injector) { setTimeout(() => this.payrollService = injector.get(PayrollService)); } 

Vedi anche Circular dependency injection angular 2

C’è un capitolo nella documentazione di Angular 2 sulla dipendenza ciclica. Penso che sia molto utile.

Iniezione di dipendenza

La chiave qui non è di iniettare il servizio tramite il costruttore, ma, invece, usa setter e getter espliciti. Vorrei utilizzare il seguente modello in Angular 4:

app.component.ts

 import { FooService } from './foo/foo.service'; import { BarService } from './bar/bar.service'; export class AppComponent { constructor(public fooService: FooService, public barService: BarService) { this.fooService.setBarService(barService); } } 

foo.service.ts

 @Injectable() export class FooService { barService: any; constructor(){ } setBarService(barService: any): void { this.barService = barService; } getBarService(): any { return this.barService; } } 

È una dipendenza circolare e sfortunatamente è un problema di informatica fondamentale, o problema di informazione, qualcosa che Angular non può risolvere. Prova a fare qualcosa come questo, invece:

 export class ServiceA{ constructor(private b: ServiceB){ b.setA(this); } } export class ServiceB { private a: ServiceA constructor(){ } setA(a){ this.a = a; } } 

questo è probabilmente il modo migliore per farlo.

Ho aggiornato questa soluzione per lavorare con Angular> 4. Utilizzando la class Injector è ansible iniettare un servizio in un altro servizio

 import { Injector } from '@angular/core'; import { TempService } from './tmp'; @Injectable() export class Temp2Service { private tempService: any; constructor (private injector: Injector) { } public funcA() { this.tempService = this.injector.get(TempService); this.tempService.doSomething(); } } 

puoi provare a chiamare NEW su uno dei servizi se non hai un singleton accettabile. piace

 this._sessionService = new TempService(this); 

Questo è stato l’approccio che ho preso da quando nessuno dei due servizi utilizzava variabili membro indefinite.

Se si utilizza Angular 2 e si richiede una dipendenza circolare per chiamare le funzioni l’uno dell’altro su alcuni eventi, è ansible utilizzare Observables e registrarli in Service in cui è stato iniettato l’altro servizio.

Piccolo esempio: –

 @Injectable() class Service1{ observeEvents(){ return Obsevable.create((o)=>{ //store `o` it in any class variable //whenever you want to call function of Service2 from this class, do this `o.next('method_name');` }); } } @Injectable() class Service2{ constructor(private service1: Service1){ this.service1.subscribe((method)=>{ this[method](); }); } } 

Possiamo risolvere la funzione forwordRef per risolvere questo problema.

// Permette di fare riferimento a riferimenti che non sono ancora definiti.

@Inject (forwardRef (() => MyService)) httpProxy privato: MyService

Usa le interfacce: questo è uno schema comune in molte lingue.

Vedi la risposta di Günters

Dipendenza circolare con Angular 2 e SystemJS