2017-04-12 77 views
9

我已经在我的应用程序中多次完成此操作。这很简单,它应该工作...但是这次它不。Angular 2:Observable/Subscription not triggereding

我的问题:

我打电话对组件进行服务的方法,我组分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

这就是为什么我添加NavigationElementsServiceIBOsNavigationElement的模块:

NavigationModuleIBOsNavigationElement的模块

@NgModule({ 
    imports: [ 
     // A lot of stuff 
    ], 
    declarations: [ 
     // A lot of stuff 
     IBOsNavigationElement 
    ], 
    exports: [ 
     // A lot of stuff 
    ], 
    providers: [ 
     NavigationElementsService 
    ] 
}) 

控制台:

CALLING updateIBOsNavigation功能

updateIBOsNavigation “95”

CALLING updateIBOsNavigation功能AGAIN

updateIBOsNavigation “测试”

此控制台结果却对我说:

  • 的方法被调用,所以没有提供者错误。 与服务沟通OK

我的测试:

  • 我已经打过电话随机方法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()不会触发,但在le因为我知道有一个NavigationElementsService的实例。

+0

我加入更新与我绝望的尝试...请结束我的折磨! xD – SrAxi

+0

嗨,你现在是否解决了这个问题? –

+0

@BonesandTeeth是的!谢谢! :D – SrAxi

回答

17

我认为问题在于您的Subject类型使用Subject,在事件发生后订阅的任何组件都不会接收到值。若要重播之前的价值给​​晚期用户使用BehaviorSubjectReplaySubject而不是Subject

更多关于不同主题类型从http://reactivex.io/documentation/subject.html

行为主题

当观察者预订BehaviorSubject时,它开始通过发射最近由源可观察发出的项目(或种子/默认值,如果还没有发射),然后继续发射源Observable(s)发射的任何其他项目。

ReplaySubject

ReplaySubject发射到任何观察者所有由源可观察(多个)被发射,该物品的,无论观察者的订阅时。

A BehaviorSubject设置时需要默认值。因此,你需要用某种价值创造它:

updateIBOsNavigationSubject = new BehaviorSubject<any>(''); 
updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable(); 

updateIBOsNavigation(navigationData) { 
    log.d('updateIBOsNavigation', JSON.stringify(navigationData)); 
    this.updateIBOsNavigationSubject.next(navigationData); 
} 

一个ReplaySubject不需要缺省值。

EDIT

当使用共享服务也是重要,以确保该服务正在仅在根模块提供。如果它提供了多个地方,那么组件可能不会获得相同的实例。即使该服务是在根级别提供的,如果根级别和组件之间的模块提供该服务,则会将新实例发送到依赖注入树的分支。

希望这会有所帮助。

+0

或'ReplaySubject',它不需要初始默认值。 – jonrsharpe

+0

正确,要么会替换最近的值。 –

+0

@TylerJennings谢谢!我试着用'BehaviorSubject'并删除'asObservable()'。它第一次工作(在初始化时),但不是每次我调用该方法。我正在尝试使用'ReplaySubject'。 – SrAxi

1

当我们在'providers'中包含一个服务时,它被实例化并且这个状态在它的组件和子组件之间被维护。

而且,如果我们在两个组件提供程序数组中都包含该服务,那么它不再跟随单例。国家将是独立的,不会在他们之间分享。

因此,只包括您的服务在父组件或您的根组件。

我也遇到了这个问题,并在此解决方案的帮助下解决,https://stackoverflow.com/a/38034298/5730167