How to wait for subscribe to finish Angular 5?

Issue

I am working on an Angular 5 app. I get an error because I have a function that executes before another function is done, hence getting a null variable. I have tried to use .map and .subscribe with Observable, but didn’t succeed. Here is the code:

loadData is called from my app.component class:

ngOnInit() {
    this.dataService.loadData(sessionStorage.getItem(...);
}

While that function executes, another function from data.component class (dataService.getData) is called on initialization:

constructor(private dataService: DataService) {}

ngOnInit() {
    this.dataTxt = this.dataService.getData(...);
}

Here is the data.service class:

loadData(... : void) {
    if (sessionStorage["data"] == null {
        this.http.request(...)
        .map((response: Response) => response.json()).subscribe(data => {
            ...
            sessionStorage.setItem("data", JSON.stringify(this.data));
            ...
        }
    }
}

getData(... : string){
    if (this.data == null) {
        this.data = JSON.parse(sessionStorage["data"]);
    }
    ...
}

The problem is that sessionStorage["data"] is null until loadData() is done and I get this error a few times:

ERROR SyntaxError: Unexpected token u in JSON at position 0
    at JSON.parse (<anonymous>)

I understand that if I want to wait for subscribe to finish, I have to put the code that need to wait (getData()) just after the subscribe call. But the function that needs to wait is called from other classes so how do I put it there?

Solution

you’re mistaken that you’d put your code "after" the subscribe handler, you’d need to put it INSIDE of the subscribe handler, but regardless,

you need to use a subject of some kind here, probably a ReplaySubject in this particular case…

private dataSource = new ReplaySubject(1) // create a private subject
data$ = this.dataSource.asObservable() // and a public observable

loadData(... : void) {
    if (sessionStorage["data"] == null {
        this.http.request(...)
        .map((response: Response) => response.json()).subscribe(data => {
            ...
            sessionStorage.setItem("data", JSON.stringify(this.data));
            this.dataSource.next(data) // set the data in the subject
            ...
        }
    }
}

then you’d subscribe to the subject in your component…

ngOnInit() {
    this.dataService.data$.pipe(first()) // avoid memory leak.
      .subscribe(data => this.dataTxt = data);
}

Answered By – bryan60

Answer Checked By – Jay B. (AngularFixing Admin)

Leave a Reply

Your email address will not be published.