Services depending on each other
This is a called circular dependency. It is not an issue with Angular2 itself. It is not allowed in any language I am aware of.
You will need to refactor your code to remove this circular dependency. Likely you will need to breakup one of these services into new service.
If you follow the single responsibility principle you will find you won't get into circular dependency trap.
Constructor injection prevents circular dependencies.
It can be broken up by injecting the Injector
and requesting a dependency imperatively like:
private payrollService:PayrollService;
constructor(/*private payrollService:PayrollService*/ injector:Injector) {
setTimeout(() => this.payrollService = injector.get(PayrollService));
}
See also Circular dependency injection angular 2
The key here is not to inject the service via the constructor, but instead, use explicit setters & getters. I would use the following pattern 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;
}
}
I updated this solution to work with Angular > 4. Using Injector class you can inject a service into another service
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();
}
}
It's a circular dependency and unfortunately it's a fundamental computer science problem, or information problem, something that Angular cannot solve. Try doing something like this instead:
export class ServiceA {
constructor(private b: ServiceB){
b.setA(this);
}
}
export class ServiceB {
private a: ServiceA
constructor(){
}
setA(a){
this.a = a;
}
}
that's probably the best way to do it.