我在我的应用程序中多次这样做了。它很简单,它应该工作......但这次它没有。
我的问题:
我在组件A中调用服务中的方法,我的组件B已订阅但不响应也不接收任何内容。 subscribe()
没有触发!
导航elements.service.ts
@Injectable()
export class NavigationElementsService {
updateIBOsNavigation$: Observable<any>;
private updateIBOsNavigationSubject = new Subject<any>();
constructor() {
this.updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable();
}
updateIBOsNavigation(navigationData) {
log.d('updateIBOsNavigation', JSON.stringify(navigationData));
this.updateIBOsNavigationSubject.next(navigationData);
}
}
IboDetailsGeneral
组件
export class IboDetailsGeneral implements OnInit, OnDestroy {
id: string;
private sub: any;
constructor(private route: ActivatedRoute, private iboService: IBOsService, private navigationService: NavigationElementsService) {
this.sub = this.route.params.subscribe(params => {
this.id = params['id'];
console.log('CALLING updateIBOsNavigation FUNCTION');
this.navigationService.updateIBOsNavigation(this.id);
});
}
ngOnInit() {
console.log('CALLING updateIBOsNavigation FUNCTION AGAIN');
this.navigationService.updateIBOsNavigation('test');
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
该组件触发服务的方法:updateIBOsNavigation
。
IBOsNavigationElement
组件
export class IBOsNavigationElement implements OnInit {
private id: string;
constructor(private navigationService: NavigationElementsService) {
this.navigationService.updateIBOsNavigation$.subscribe((navigationData) => {
log.d('I received this Navigation Data:', JSON.stringify(navigationData));
this.id = navigationData;
}
);
}
ngOnInit() {
}
}
该组件已订阅,应列出并接收数据...
让我们理清DI:考虑到IboDetailsGeneral
位于App结构的较低层,所以IboDetailsGeneral
是IBOsNavigationElement
的孩子。
这就是为什么我将NavigationElementsService
添加到IBOsNavigationElement
的模块中:
NavigationModule
是IBOsNavigationElement
的模块
@NgModule({
imports: [
// A lot of stuff
],
declarations: [
// A lot of stuff
IBOsNavigationElement
],
exports: [
// A lot of stuff
],
providers: [
NavigationElementsService
]
})
安慰:
调用updateIBOsNavigation功能
updateIBOsNavigation“95”
再次呼叫updateIBOsNavigation功能
updateIBOsNavigation“test”
这个控制台结果告诉我:
我的测试:
IBOsNavigationElement
(监听器)中调用随机方法,并且与服务的通信很好。NavigationElementsService
添加到providers
的唯一地方是NavigationModule
,所以只有一个服务实例吗?然后,以下链接中解释的问题不会发生:Angular 2 observable subscription not triggering我真的很抱歉我的“文本墙”,但在这一点上,我有点绝望。
任何帮助表示赞赏,谢谢!
更新1:
在第一个答案之后我尝试了几件事......
使用ReplaySubject
:
@Injectable()
export class NavigationElementsService {
public updateIBOsNavigation$ = new ReplaySubject();
updateIBOsNavigation(navigationData) {
log.d('updateIBOsNavigation', JSON.stringify(navigationData));
this.updateIBOsNavigation$.next(navigationData);
}
}
结果:当调用updateIBOsNavigation()
时,subscribe()
仍未触发。
使用BehaviorSubject
:
@Injectable()
export class NavigationElementsService {
updateIBOsNavigationSubject = new BehaviorSubject<any>('');
updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable();
updateIBOsNavigation(navigationData) {
log.d('updateIBOsNavigation', JSON.stringify(navigationData));
this.updateIBOsNavigationSubject.next(navigationData);
}
}
结果:它在初始化时进入subscribe()
但是当我调用updateIBOsNavigation()
时,subscribe()
仍未触发。
使用BehaviorSubject
v2:
我试过这种方法:behaviourSubject in angular2 , how it works and how to use it
@Injectable()
export class NavigationElementsService {
public updateIBOsNavigation$: Subject<string> = new BehaviorSubject<string>(null);
updateIBOsNavigation(navigationData) {
log.d('updateIBOsNavigation', JSON.stringify(navigationData));
this.updateIBOsNavigation$.next(navigationData);
}
}
结果:与先前的BehaviorSubject
申请相同。
更新2:
在整个网络上进行研究后,更多的绝望尝试样本......
使用BehaviorSubject
v3:
@Injectable()
export class NavigationElementsService {
updateIBOsNavigation$: Observable<any>;
updateIBOsNavigationSubject = <BehaviorSubject<any>> new BehaviorSubject([]);
constructor() {
this.updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable();
}
updateIBOsNavigation(navigationData) {
log.d('updateIBOsNavigation()', JSON.stringify(navigationData));
this.updateIBOsNavigationSubject.next(navigationData);
}
}
结果:与以前的BehaviorSubject
尝试相同......绝望正在上升......
更新3:
为了以防万一,我想确保NavigationElementsService
是一个单身人士:
export class NavigationModule {
static forRoot() {
return {
ngModule: NavigationModule,
providers: [NavigationElementsService]
};
}
}
并在导入时:
imports: [
NavigationModule.forRoot()
]
结果:问题一如既往,subscribe()
没有触发,但至少我知道有一个NavigationElementsService
实例。
我认为问题是你的Subject
类型使用Subject
,在事件触发后订阅的任何组件都不会收到值。要将之前的值重播给后期订阅者,请使用BehaviorSubject
或ReplaySubject
而不是Subject
。
更多关于http://reactivex.io/documentation/subject.html的不同主题类型
行为主体
当观察者订阅BehaviorSubject时,它首先发出源Observable最近发出的项(或者如果尚未发出种子/默认值),然后继续发出源Observable稍后发出的任何其他项( S)。
ReplaySubject
无论观察者何时订阅,ReplaySubject都会向任何观察者发出源Observable发出的所有项目。
设置时,BehaviorSubject
确实需要默认值。所以你需要创建一些有价值的东西:
updateIBOsNavigationSubject = new BehaviorSubject<any>('');
updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable();
updateIBOsNavigation(navigationData) {
log.d('updateIBOsNavigation', JSON.stringify(navigationData));
this.updateIBOsNavigationSubject.next(navigationData);
}
ReplaySubject
不需要默认值。
编辑
使用共享服务时,确保仅在根模块上提供服务也很重要。如果提供多个位置,则组件可能无法获得相同的实例。即使服务是在根级别提供的,如果根级别和组件之间的模块提供服务,则新实例将在依赖注入树的该分支下发送。
希望这可以帮助。
当我们在'providers'中包含一个服务时,它就会被实例化,并且在它的组件及其子组件之间保持这种状态。
而且,如果我们在两个组件提供程序数组中包含该服务,那么它就不再是单例。国家将是独立的,不会在他们之间分享。
因此,仅在父组件或根组件中包含您的服务。
我也遇到了这个问题,并在这里解决了这个问题,https://stackoverflow.com/a/38034298/5730167。