角度2:可观察/订阅未触发 [英] Angular 2: Observable / Subscription not triggering
问题描述
我已经在我的App中多次进行了此操作.很简单,它应该可以工作...但是这次没有.
I have done this multiple times in my App. It's simple, it should work... But this time it doesn't.
我的问题:
我正在从组件A调用服务中的方法,我的组件B已订阅,但不响应也不接收任何内容. subscribe()
没有触发!
I am calling a method in a service from a Component A, my Component B is subscribed but doesn't react nor receive anything. subscribe()
is not triggering!
navigation-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
组件
IboDetailsGeneral
component
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
.
This component triggers the service's method: updateIBOsNavigation
.
IBOsNavigationElement
组件
IBOsNavigationElement
component
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() {
}
}
该组件已订阅,应该列出并接收数据...
This component is subscribed, it should listed and receive the data...
让我们整理一下DI:
考虑到IboDetailsGeneral
位于应用程序结构的下层,因此IboDetailsGeneral
是IBOsNavigationElement
的 child .
Let's sort out DI:
Take into account that IboDetailsGeneral
is in a lower layer on the App's structure, so IboDetailsGeneral
is child of IBOsNavigationElement
.
这就是为什么我将NavigationElementsService
添加到IBOsNavigationElement
的模块中的原因:
This is why I add NavigationElementsService
into IBOsNavigationElement
's module:
NavigationModule
是IBOsNavigationElement
的模块
NavigationModule
is IBOsNavigationElement
's module
@NgModule({
imports: [
// A lot of stuff
],
declarations: [
// A lot of stuff
IBOsNavigationElement
],
exports: [
// A lot of stuff
],
providers: [
NavigationElementsService
]
})
控制台:
调用updateIBOsNavigation功能
CALLING updateIBOsNavigation FUNCTION
updateIBOsNavigation"95"
updateIBOsNavigation "95"
再次致电更新IBOsNavigation功能
CALLING updateIBOsNavigation FUNCTION AGAIN
updateIBOsNavigation测试"
updateIBOsNavigation "test"
此控制台结果告诉我:
- 该方法正在被调用,因此没有提供程序错误. 可以与服务进行通信.
我的测试:
- 我尝试在
IBOsNavigationElement
(侦听器)中调用随机方法,并且与服务的通信良好. - 将
NavigationElementsService
添加到providers
的唯一位置是在NavigationModule
中,因此只有一个服务实例吗?然后,以下链接中说明的问题不会发生: Angular 2的可观察订阅没有触发
- I have tried calling a random method in
IBOsNavigationElement
(the listener), and communication with service is good. - The only place where
NavigationElementsService
is added toproviders
is inNavigationModule
, so there is only one instance of the service right? Then, the issue explained in the following link doesn't take place: Angular 2 observable subscription not triggering
我真的很抱歉我的文字墙" ,但在这一点上,我感到很绝望.
I am really sorry for my 'wall of text' but at this point I am kind of desperate.
感谢您的帮助,谢谢!
更新1:
在第一个答案之后,我尝试了几件事...
After the first answer I have tried several things...
使用ReplaySubject
:
Using ReplaySubject
:
@Injectable()
export class NavigationElementsService {
public updateIBOsNavigation$ = new ReplaySubject();
updateIBOsNavigation(navigationData) {
log.d('updateIBOsNavigation', JSON.stringify(navigationData));
this.updateIBOsNavigation$.next(navigationData);
}
}
结果:调用updateIBOsNavigation()
时,subscribe()
仍未触发.
Result: When calling updateIBOsNavigation()
, subscribe()
is still not triggering.
使用BehaviorSubject
:
Using 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()
仍未触发.
Result: It enters subscribe()
on initialization but when I call updateIBOsNavigation()
, subscribe()
is still not triggering.
使用BehaviorSubject
v2:
Using BehaviorSubject
v2:
我尝试了这种方法: behaviourSubject angular2,它如何工作以及如何使用
@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
的先前应用相同.
Result: Same as previous application of BehaviorSubject
.
更新2:
在整个网络上进行搜索后,更多绝望尝试的示例...
More samples of desperate attempts after researching throughout the web...
使用BehaviorSubject
v3:
Using 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
尝试相同...绝望情绪正在上升...
Result: Same as previous BehaviorSubject
attempts... Desperation is rising...
更新3:
以防万一,我想确保NavigationElementsService
是 singleton :
Just in case, I wanted to make sure that NavigationElementsService
is a singleton:
export class NavigationModule {
static forRoot() {
return {
ngModule: NavigationModule,
providers: [NavigationElementsService]
};
}
}
导入时:
imports: [
NavigationModule.forRoot()
]
结果:与往常一样,subscribe()
没有触发,但至少我知道有一个NavigationElementsService
实例.
Result: Same issue as always, subscribe()
not triggering, but at least I know that there is one instance of NavigationElementsService
.
推荐答案
我认为问题是您的Subject
类型使用Subject
时,在事件触发后进行预订的任何组件都不会收到值.要将先前的值重播给后期订阅者,请使用BehaviorSubject
或ReplaySubject
而不是Subject
.
I think the issue is your Subject
type With Subject
, any component that subscribes after an event has fired will NOT receive a value. To replay the previous value to late subscribers use BehaviorSubject
or ReplaySubject
instead of Subject
.
有关 http://reactivex.io/documentation/subject.html
行为主题
当观察者订阅一个BehaviorSubject时,它首先发出源Observable最近发出的项目(如果尚未发出,则为种子/默认值),然后继续发出后来由该Observable发出的任何其他项目.源可观察到的.
When an observer subscribes to a BehaviorSubject, it begins by emitting the item most recently emitted by the source Observable (or a seed/default value if none has yet been emitted) and then continues to emit any other items emitted later by the source Observable(s).
ReplaySubject
ReplaySubject向观察者发出源Observable发出的所有项目,无论观察者何时订阅.
ReplaySubject emits to any observer all of the items that were emitted by the source Observable(s), regardless of when the observer subscribes.
BehaviorSubject
设置时确实需要默认值.因此,您需要使用某种值来创建它:
A BehaviorSubject
does require a default value when setting it up. So you'd need to create it with some sort of value:
updateIBOsNavigationSubject = new BehaviorSubject<any>('');
updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable();
updateIBOsNavigation(navigationData) {
log.d('updateIBOsNavigation', JSON.stringify(navigationData));
this.updateIBOsNavigationSubject.next(navigationData);
}
ReplaySubject
不需要默认值.
编辑
使用共享服务时,确保仅在根模块上提供该服务也很重要.如果提供了多个位置,则组件可能不会获得相同的实例.即使该服务是在根级别提供的,但如果根级别和您的组件之间的模块提供了该服务,则新实例将在依赖注入树的该分支下发送.
When using a shared service it is also important to make sure the service is being provided ONLY at the root module. If it is provided multiple places, then the components may not be getting the same instance. Even if the service is provided at the root level, if a module between the root level and your component provides the service, a new instance will get sent down that branch of the Dependency Injection tree.
希望这会有所帮助.
这篇关于角度2:可观察/订阅未触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!