Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular - two subscriptions in ngOnInit result in object 'undefined'

In short.. I am not able to access my news object. It is coming back as 'undefined' when called in a function.

In my ngOnInit I have two subscriptions. First one returns a news object (which is defined as a global variable at the top of the component).

The second subscription returns a route parameter and then triggers a function (navigateToArticle).

Now... when the second subscription triggers the 'navigateToArticle' function, I want that function to be able to access the news object.

However, every time I try to console log the news object, it comes back as 'undefined'. Now I understand that this is something to do with the subscriptions being asynchronous.

So my question is, how can I ensure that the news object has been loaded and accessible to the 'navigateToArticle' function. Possibly some kind of check to see if news has been loaded?

Sorry, I'm new to Angular so please go easy. I'm sure I'm missing something very simple. I've stripped code down to bare minimum for clarity.

public news: Newswire;

ngOnInit() {

    this._newswireService.getSectors().subscribe((news: Newswire) => {
      this.news = news;
    }

    this._activatedRoute.paramMap.subscribe(params => {
       this.newsID = params.get('id');
       this.navigateToArticle();
    })

}

public navigateToArticle() {
    console.log(this.news);
}
like image 943
Slava Kuznetsov Avatar asked Apr 11 '19 17:04

Slava Kuznetsov


1 Answers

If you want to return observables in a sequential manner, you shouldn't nest your subscribe() methods. Instead, we should be using RxJS's mergeMap to map over the observable values from the activatedRoute into an inner observable, which is assigned to the newsID property. Then, we call the getSectors() method from _newswireService, and the observables are returned in subscribe() on the subsequent line. This way, your news will not be undefined.

Do not forget to import mergeMap onto your component!

import { mergeMap } from 'rxjs/operators';

//.
//.

this._activatedRoute.paramMap.pipe(
  mergeMap(params => {
    this.newsID = params.get('id');
    return this._newswireService.getSectors();
  })
).subscribe(res => {
  this.news = news;
  this.navigateToArticle();
})
like image 91
wentjun Avatar answered Sep 26 '22 23:09

wentjun