Angular2. How can I check if an observable is completed?

38,775

Solution 1

You can do this by using onCompleted callback in subscription. For example, let's say you show loading bar when user press report button;

loadCompanies(): void {
     this._companyService.getCompanies().subscribe(
          response => {
               this.companiesModel = response;
          },
          err => {
               console.log(err);
               //closeLoadingBar();
          },
          () => {
               //do whatever you want
               //closeLoadingBar()
          }
     )
}

generateReport() {
    //showLoadingBar()
    this.loadCompanies();
}

If you get error from your http call, onCompleted method will not be invoked, only onError will be invoked. If it is successful, onCompleted method will be called after your onNext method.

Here is the documentation for subscribe. I hope it helps!

Solution 2

One more solution:

Actually subscribe function takes three parameters:

onNext onError onCompleted

this._companyService.getCompanies().subscribe(
    (response) => { this.companiesModel = response; },
    (err) => { console.log(err) },
    (finally) => { console.log('finally') }
);

Solution 3

Method

finally()

Invokes a specified action after the source observable sequence terminates gracefully or exceptionally.

https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/finally.md

Solution 4

In this kind of scenarios it is very useful to use concatMap operator to guarantee to execute the next operation only when the previous has done.

loadCompanies(): void {
    this._companyService.getCompanies()
    .concatMap(companyList => this.getObservableGenerateReport(companyList))
    .subscribe(
        response => {
            this.companiesModel = response;
        },
        err => console.log(err)
    );
}


//Create observable to generate the report
getObservableGenerateReport(response: any): Observable<myReportList> {

    return Observable.create(observer => {

      if (generateReport().isSuccessful) {
        observer.next(myReportList);
        observer.complete();
      } else {
        console.log(err, 'Ups, something was wrong!');
        observer.next({});
        observer.complete();
      }

    });
  }

Solution 5

If you're doing this to debug, the simplest solution is to use the complete argument of tap:

tap(next: null, error: null, complete: () => void)

With a source source$ it would look like this:

source$.pipe(
  tap(undefined, undefined, console.log)
);
Share:
38,775
csm86
Author by

csm86

Updated on July 21, 2022

Comments

  • csm86
    csm86 almost 2 years

    In my page there is a button that generates a report. That report needs data that is loaded using a http call to a rest endpoint when the page is loaded, but I do not have a guarantee that they are loaded when the user presses the report button.

    How can I watch the observable to see if it is completed, and if incomplete, to wait on the action until the http call is completed? Here is some of the code:

    loadCompanies(): void {
        this._companyService.getCompanies().subscribe(
            response => {
                this.companiesModel = response;
            },
            err => console.log(err)
        );
    }
    
    generateReport() {
       // check if observable that loads companies is completed and do the 
       // action using companiesModel.
    } 
    

    One option is a flag set in loading companies with values of 'loading' and 'completed', and make a wait in generateReport() until the flag is completed, but I would prefer a solution using the Observable API if possible.