我在一个真实的项目中有一个真实的场景,我需要2个服务来访问彼此的属性和/或方法。我不是Angular专家,所以有可能吗?
我试过但失败了。这是我的尝试:
app.component.ts
import { Component } from '@angular/core';
import { FirstService } from './first.service';
import { SecondService } from './second.service';
@Component({
selector: 'my-app',
template: '<h1>Hello world!</h1>',
providers: [FirstService, SecondService]
})
export class AppComponent {
constructor(public firstService: FirstService, public secondService: SecondService) {
console.log(firstService.foo);
console.log(secondService.bar);
}
}
first.service.ts
import { Injectable } from '@angular/core';
import { SecondService } from './second.service';
@Injectable()
export class FirstService {
foo: string = 'abc';
constructor(public secondService: SecondService) {
this.foo = this.foo + this.secondService.bar;
}
}
second.service.ts
import { Injectable } from '@angular/core';
import { FirstService } from './first.service';
@Injectable()
export class SecondService {
bar: string = 'xyz';
constructor(public firstService: FirstService) {
this.bar = this.bar + this.firstService.foo;
}
}
Plunker:http://plnkr.co/edit/PQ7Uw1WHpvzPRf6yyLFd?p=preview
将第二个服务注入到第一个服务中工作正常但是只要我将第一个服务注入第二个服务就会失败并向控制台抛出错误。
那有什么不对?
工作解决方案应将以下内容打印到控制台日志:
abcxyz
xyzabc
提前致谢!
答案 0 :(得分:3)
我不是角色专家所以可能
没有。角度的DI不能解决循环依赖关系。
即使是支持它的系统,通常也是不一致的,例如commonjs https://nodejs.org/docs/latest/api/modules.html#modules_cycles会在一段时间内给你一个空对象。
考虑将两个服务合并到 one 中。如果组合服务变得太多,你仍然可以将某些东西(例如简单的功能等)移出。
答案 1 :(得分:3)
AngularJS不允许注入循环依赖。
AngularJS的作者之一MiškoHevery建议找到共同的元素:
+---------+ +---------+
| A |<-----| B |
| | | | +-+ |
| | | +->|C| |
| |------+---->| | |
| | | +-+ |
+---------+ +---------+
将其提取到第三项服务:
+---------+
+---------+ | B |
| A |<-------------| |
| | | |
| | +---+ | |
| |--->| C |<----| |
| | +---+ +---------+
+---------+
有关详细信息,请参阅MiškoHevery Circular Dependency in constructors and Dependency Injection。
答案 2 :(得分:2)
我同意basarat提出的解决方案。另一种解决方法是初始化DI之外的实例并将它们提供为
之类的值需要修改一个服务才能创建实例而不将其他服务作为依赖项提供:
@Injectable()
export class FirstService {
foo: string = 'abc';
secondService: SecondService
constructor() {
//this.foo = this.foo + this.secondService.bar;
}
init(secondService:SecondService) {
this.foo = this.foo + secondService.bar;
}
}
然后命令性地创建实例并将它们作为值
提供let firstService = new FirstService();
let secondService = new SecondService(firstService);
@Component({
selector: 'my-app',
template: '<h1>Hello world!</h1>',
providers: [
provide(FirstService, {useFactory: () => {
firstService.init(secondService);
return firstService;
}}), provide(SecondService, {useValue: secondService})]
})
...