[英]Angular 2: Observable / Subscription not triggering
我在我的应用程序中多次这样做了。 很简单,它应该可以工作……但这次不行。
我的问题:
我正在从组件 A 调用服务中的方法,我的组件 B 已订阅但没有反应也没有收到任何东西。 subscribe()
没有触发!
导航元素.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
位于应用程序结构的较低层,因此IboDetailsGeneral
是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
]
})
安慰:
调用更新IBOsNavigation FUNCTION
更新IBOsNavigation "95"
再次调用更新IBOs导航功能
更新IBOsNavigation“测试”
这个控制台结果告诉我:
我的测试:
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:
我尝试了这种方法: angular2 中的 behaviorSubject ,它是如何工作的以及如何使用它
@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
类型 With Subject
,在事件触发后订阅的任何组件都不会收到值。 要将先前的值重播给迟到的订阅者,请使用BehaviorSubject
或ReplaySubject
而不是Subject
。
更多关于不同主题类型的信息来自http://reactivex.io/documentation/subject.html
行为主体
当观察者订阅 BehaviorSubject 时,它首先发射源 Observable 最近发射的项目(如果尚未发射,则为种子/默认值),然后继续发射源 Observable 稍后发射的任何其他项目( s)。
重播主题
ReplaySubject 将源 Observable(s) 发出的所有项目发送给任何观察者,而不管观察者何时订阅。
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 。
就我而言,我在父模块“app.module”和子模块中使用了相同的服务。 我从子模块中的 Provider 部分删除了服务。 有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.