Search code examples
angularangular5observableangular2-observables

Angular 5 wait for multiple child notifications


I have a parent component that includes two child components. Each of the children has their own network load, and I need to know in the parent component when both children are done with their network loads. I had assumed I could use an observable for this but it didn't work for me. In both my child components I did this:

private _loadFinished = new BehaviorSubject<boolean>(null);
loadFinished = this._loadFinished.asObservable();

networkLoad() {
   this.network.doLoad().subscribe(x => {
       this._loadFinished.next(true);
   });
}

In the parent's HTML, I tagged each child component and then in the code I did this:

@ViewChild('orgMetrics') orgMetrics: ChildComponentOne;
@ViewChild('campusMetrics') campusMetrics: ChildComponentTwo;

loading = true;

ngOnInit(): void {
    forkJoin(
        this.orgMetrics.loadFinished,
        this.campusMetrics.loadFinished
    ).subscribe(() => {
        console.info("I got here");
        this.loading = false;
    }, () => this.loading = false);
}

}

The subscribe is never getting hit though. Am I going the completely wrong direction here? I was also looking at en EventEmitter but I didn't understand how I would wait for both to be done before taking action.


Solution

  • The forkJoin function will emit only when the given Observables have completed. i.e., it will not emit when the Observables you give it simply emit values of their own.

    Because you are using BehaviorSubject, calling this._loadFinished.next(true) will only emit a single value from the Observable, and it will not complete.

    A quick fix is to simply call _loadFinished.complete() after emitting the one and only value:

    networkLoad() {
       this.network.doLoad().subscribe(x => {
           this._loadFinished.next(true);
           this._loadFinished.complete();
       });
    }
    

    If you had some reason to keep the BehaviorSubjects around, you might also find the Observable.combineLatest operator more appropriate, as it simply looks for the latest emitted values from an Observable.