[英]Angular 2: Observable / Subscription not triggering
I have done this multiple times in my App.我在我的应用程序中多次这样做了。 It's simple, it should work... But this time it doesn't.
很简单,它应该可以工作……但这次不行。
My issue:我的问题:
I am calling a method in a service from a Component A, my Component B is subscribed but doesn't react nor receive anything.我正在从组件 A 调用服务中的方法,我的组件 B 已订阅但没有反应也没有收到任何东西。
subscribe()
is not triggering! subscribe()
没有触发!
navigation-elements.service.ts导航元素.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
component 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();
}
}
This component triggers the service's method: updateIBOsNavigation
.此组件触发服务的方法:
updateIBOsNavigation
。
IBOsNavigationElement
component 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() {
}
}
This component is subscribed, it should listed and receive the data...此组件已订阅,它应该列出并接收数据...
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
.让我们梳理一下 DI:考虑到
IboDetailsGeneral
位于应用程序结构的较低层,因此IboDetailsGeneral
是IboDetailsGeneral
的子IBOsNavigationElement
。
This is why I add NavigationElementsService
into IBOsNavigationElement
's module:这就是我将
NavigationElementsService
添加到IBOsNavigationElement
的模块的原因:
NavigationModule
is IBOsNavigationElement
's module NavigationModule
是IBOsNavigationElement
的模块
@NgModule({
imports: [
// A lot of stuff
],
declarations: [
// A lot of stuff
IBOsNavigationElement
],
exports: [
// A lot of stuff
],
providers: [
NavigationElementsService
]
})
Console:安慰:
CALLING updateIBOsNavigation FUNCTION
调用更新IBOsNavigation FUNCTION
updateIBOsNavigation "95"
更新IBOsNavigation "95"
CALLING updateIBOsNavigation FUNCTION AGAIN
再次调用更新IBOs导航功能
updateIBOsNavigation "test"
更新IBOsNavigation“测试”
This console results tells me that:这个控制台结果告诉我:
My tests:我的测试:
IBOsNavigationElement
(the listener) , and communication with service is good.IBOsNavigationElement
(侦听器)中调用随机方法,并且与服务的通信良好。NavigationElementsService
is added to providers
is in NavigationModule
, so there is only one instance of the service right? NavigationElementsService
添加到providers
的唯一地方是在NavigationModule
,所以只有一个服务实例,对吗? 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.我真的很抱歉我的“文字墙”,但在这一点上我有点绝望。
Any help is appretiated, thank you!任何帮助表示赞赏,谢谢!
Update 1:更新 1:
After the first answer I have tried several things...在第一个答案之后,我尝试了几件事......
Using ReplaySubject
:使用
ReplaySubject
:
@Injectable()
export class NavigationElementsService {
public updateIBOsNavigation$ = new ReplaySubject();
updateIBOsNavigation(navigationData) {
log.d('updateIBOsNavigation', JSON.stringify(navigationData));
this.updateIBOsNavigation$.next(navigationData);
}
}
Result: When calling updateIBOsNavigation()
, subscribe()
is still not triggering.结果:调用
updateIBOsNavigation()
, subscribe()
仍未触发。
Using BehaviorSubject
:使用
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);
}
}
Result: It enters subscribe()
on initialization but when I call updateIBOsNavigation()
, subscribe()
is still not triggering.结果:它在初始化时进入
subscribe()
但当我调用updateIBOsNavigation()
, subscribe()
仍然没有触发。
Using BehaviorSubject
v2:使用
BehaviorSubject
v2:
I tried this approach: behaviourSubject in angular2 , how it works and how to use it我尝试了这种方法: 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);
}
}
Result: Same as previous application of BehaviorSubject
.结果:与之前的
BehaviorSubject
应用程序相同。
Update 2:更新 2:
More samples of desperate attempts after researching throughout the web...在整个网络上进行研究后,更多绝望的尝试样本......
Using BehaviorSubject
v3:使用
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);
}
}
Result: Same as previous BehaviorSubject
attempts... Desperation is rising...结果:与之前的
BehaviorSubject
尝试相同……绝望正在上升……
Update 3:更新 3:
Just in case, I wanted to make sure that NavigationElementsService
is a singleton :以防万一,我想确保
NavigationElementsService
是一个单例:
export class NavigationModule {
static forRoot() {
return {
ngModule: NavigationModule,
providers: [NavigationElementsService]
};
}
}
And when importing:导入时:
imports: [
NavigationModule.forRoot()
]
Result: Same issue as always, subscribe()
not triggering, but at least I know that there is one instance of NavigationElementsService
.结果:与往常一样的问题,
subscribe()
没有触发,但至少我知道有一个NavigationElementsService
实例。
I think the issue is your Subject
type With Subject
, any component that subscribes after an event has fired will NOT receive a value.我认为问题在于您的
Subject
类型 With Subject
,在事件触发后订阅的任何组件都不会收到值。 To replay the previous value to late subscribers use BehaviorSubject
or ReplaySubject
instead of Subject
.要将先前的值重播给迟到的订阅者,请使用
BehaviorSubject
或ReplaySubject
而不是Subject
。
More on different Subject types from http://reactivex.io/documentation/subject.html更多关于不同主题类型的信息来自http://reactivex.io/documentation/subject.html
Behavior Subject
行为主体
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).
当观察者订阅 BehaviorSubject 时,它首先发射源 Observable 最近发射的项目(如果尚未发射,则为种子/默认值),然后继续发射源 Observable 稍后发射的任何其他项目( s)。
ReplaySubject
重播主题
ReplaySubject emits to any observer all of the items that were emitted by the source Observable(s), regardless of when the observer subscribes.
ReplaySubject 将源 Observable(s) 发出的所有项目发送给任何观察者,而不管观察者何时订阅。
A BehaviorSubject
does require a default value when setting it up. BehaviorSubject
在设置时确实需要一个默认值。 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);
}
A ReplaySubject
does not require a default value. ReplaySubject
不需要默认值。
EDIT编辑
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.
即使服务是在根级别提供的,如果根级别和您的组件之间的模块提供服务,一个新的实例将被发送到依赖注入树的那个分支。
Hope this helps.希望这可以帮助。
When we include a service in 'providers', then it is instantiated and this state is maintained between its component as well as its child components.当我们在 'providers' 中包含一个服务时,它会被实例化,并且这个状态在它的组件和它的子组件之间保持。
And, if we include the service in both components provider array, then it is no more following singleton.而且,如果我们将服务包含在两个组件提供者数组中,那么它就不再是单例了。 The state will be independent and not shared between them.
状态将是独立的,不会在它们之间共享。
So, include your service only at parent component or your root component.因此,仅在父组件或根组件中包含您的服务。
I too faced this issue and solved with help of this solution here, https://stackoverflow.com/a/38034298/5730167 .我也遇到了这个问题,并在此解决方案的帮助下解决了这个问题, https://stackoverflow.com/a/38034298/5730167 。
In my case I was using the same service at parent module "app.module" and in child module as well.就我而言,我在父模块“app.module”和子模块中使用了相同的服务。 I Removed Service from Provider section in Child Module.
我从子模块中的 Provider 部分删除了服务。 It Worked.
有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.