0

I have a component that listens to http calls for displaying loaders. I have spinner component and a spinner service having a spinnerEvent$ Angular4 Event Emitter. Here is my component constructor.

constructor(
    private spinnerService: SpinnerService
) {
    this.subscription = spinnerService.spinnerEvent$.subscribe((spinnerEvent: any) => this.updateSpinnerState(spinnerEvent));
    console.log(this.subscription);
}

For the angular application lazy loading is being used. The issue is that I want to add this component to the app.component.html below the router-outlet but on doing so, my subscription method never gets fired. The subscription appears as defined on my logs. When I place the same component on the child modules, the subscription starts working. Both the spinner component and the spinner service are in a shared module that has been injected into the app.module.ts. I am not sure what causes this difference in behavior of the subscription.

Abhishek Pandey
  • 300
  • 1
  • 13
  • 1
    What you pass to `subscribe(...)` is called when `spinnerEvent$` emits an event. `console.log(...)` is executed loooong before that. Read up on async execution. – Günter Zöchbauer Jan 05 '18 at 12:34
  • 1
    »having a spinnerEvent$ Angular4 Event Emitter« EventEmitter is meant exclusively for components. You should not use it and manually subscribe to it. Use an actual rxjs Subject for that. – Ingo Bürk Jan 05 '18 at 17:48
  • @GünterZöchbauer Although it should be mentioned that observables *can* emit synchronously. They just also can emit asynchronously. – Ingo Bürk Jan 05 '18 at 17:49
  • @IngoBürk not sure what you mean. While emitting an event can be done sync, from the view of the subscriber it's always an async API. You only get a value when the callback gets called. – Günter Zöchbauer Jan 05 '18 at 18:13
  • @GünterZöchbauer `const source$ = new BehaviorSubject(42); let value = undefined; source$.subscribe(v => value = v); console.log(value);` will log `42` without an issue (arguably such code is still broken of course). But perhaps we're talking about different things; I'm just now noticing that the code in the OP logs the subscription, not a value that has been captured in the observer. – Ingo Bürk Jan 05 '18 at 18:33
  • 1
    @IngoBürk I think we are on the same page, I just think this confuses a beginner more than it helps. When an observable is used to call asyn code like an HTTP request, it orobably won't help ti explain that the event is emitted sync ;-) – Günter Zöchbauer Jan 05 '18 at 18:37
  • Fair enough. :-) – Ingo Bürk Jan 05 '18 at 19:09
  • @IngoBürk Yes, you are right there. I have changed it to a RxJs subject but the problem still remains. Also, I have logged the subscription to verify that has the subscription is active. The value emitted has been captured in the updateSpinnerState(spinnerEvent) method. – Abhishek Pandey Jan 06 '18 at 02:28
  • @GünterZöchbauer I do understand the async execution process. So, when the spinnerEvent$ emits an event, the event is not getting captured in my subscription when the spinner component is on my app.component although my subscription object is defined when I log it. On placing the same spinner component individually on the root component of the child modules, the events are received in the subscription. – Abhishek Pandey Jan 06 '18 at 02:35

1 Answers1

0

This issue got fixed when I moved my spinner component and spinner service from the shared module and defined it in the app.module. Currently trying to understand why, as my app.module had the component imported from shared module previously.

Abhishek Pandey
  • 300
  • 1
  • 13
  • So, it was a DI issue. Because of lazy loading being used in the application my root module did not have access to the SpinnerService. By using a static method forRoot in the sharedModule definition, I was able to service available in the root module. [ Ref ] (https://angular-2-training-book.rangle.io/handout/modules/shared-di-tree.html) – Abhishek Pandey Jan 08 '18 at 07:02