0

I have got a problem with the subscription in Ionic 4 page. The subscribe method is just being fired when I load the page through its route directly in the browser. If I navigate to the page throughout a router link the subscribe method is not fired.

I am using Ionic Tabs and read a few GitHub issues that state that the lifecycle events are not working correctly between the tabs navigation.

Please see the following code from my page (score.page.ts):

ngAfterViewInit() {
    console.log('ngAfterViewInit');
    this.productService.points.subscribe(
        (e) => console.log('score points', e)
    );
}

ionViewDidLoad() { console.log('ionViewDidLoad'); }

ngOnInit(): void {
    console.log('ngOnInit');
}

ionViewWillEnter() { console.log('ionViewWillEnter'); }

ionViewDidEnter() { console.log('ionViewDidEnter'); }

ionViewWillLeave() { console.log('ionViewWillLeave'); }

ionViewDidLeave() { console.log('ionViewDidLeave'); }

ionViewWillUnload() { console.log('ionViewWillUnload'); }

ngOnDestroy() {
    console.log('ngOnDestroy');
}

Console output with directly loaded /app/home/score:

console output: working

As you can see, the lifecycle events are working correctly and the subscribe method has been called as excpected.


As I load /app/home and navigate to /app/home/score (I tried a routerlink and router.navigate), the console log of the subscription is missing:

console output: not working

This is a huge problem since I need to display data dynamically on the different pages, and this is not possible if I cannot subscribe to an Observable from my service.

I also tried {{ productService.points | async }} in the template since then angular deals with the subscription itself, but the error stays the same.

productService.pointsis of type Observable<Number> but the error occurs on other Observables too.

Should I file an issue for that or am I just missing something?
Please comment if you need something else.

Thanks in advance

bene-we
  • 761
  • 11
  • 23
  • Can you tell me where exactly when you are emitting the data mean this.productService.points – Abhijit Chakra Jul 06 '19 at 07:00
  • `this.points = this.transactions.pipe( map((transactions) => transactions.map(t => t.points)), map((t) => t.reduce((sum, points) => sum + points)) );` points is transformed array from a vaueChanges() function from firestore – bene-we Jul 06 '19 at 11:09

2 Answers2

1

Its not the issue with subscription, the success subscription will only execute when the observable this.productService.points emits anything. You should check what is causing the observable to emit when navigating directly vs not when using tabs.

You can confirm the subscription is being attached by assigning subscription to a variable & console.log the subscription object.

const iSubscription: Subscription = this.productService.points.subscribe(
        (e) => console.log('score points', e)
    );
console.log(iSubscription);
rtpHarry
  • 13,019
  • 4
  • 43
  • 64
Amith Kumar
  • 4,400
  • 1
  • 21
  • 28
  • Thanks for your answer, but I don't see your point in the attached subscription. I already tried saving the subscription in a variable and log it, but I do not see any relevant data. The Observable emits from my service that gets it's data from firestore. This service is injected in both my HomePage and my ScorePage and therefore should emit correctly. What could stop the Observable to emit the values? – bene-we Jul 06 '19 at 11:14
  • Okay I thing I got what you meant! Because `points` from my `ProductService` emits before I subscribe to it, the subscription won't get any value at all. Instead I need to use a BehaviorSubject for example, because everytime subscribing to it it emits the last value. [This](https://stackoverflow.com/a/40231605/7456806) helped me to understand. – bene-we Jul 07 '19 at 19:04
  • 1
    Well I am glad your problem is figured out by using BehaviorSubject. – Amith Kumar Jul 08 '19 at 21:10
0

The solution is to use a BehaviorSubject (or ReplaySubject) instead of an Observable.

Please have a look on this answer, and also on this blog post:

Subject has one particularity that prevents us from using it to build observable data services: if we subscribe to it we won't get the last value, we will have to wait until some part of the app calls next().

This poses a problem especially in bootstrapping situations, where the app is still initializing and not all subscribers have registered, for example not all async pipes had the chance to register themselves because not all templates are yet initialized.

I will update this answer as soon as I can provide a working code example.

Community
  • 1
  • 1
bene-we
  • 761
  • 11
  • 23