Dismiss Loading Component when HTTP request finish

#1

HI Everyone

I was trying to figure out how to make the LoadingControlller work with an HTTP request. I didn’t find a solution to this in the forum or stackoverflow.

Thinking a little bit i find this way to: fire Loading component -> make an HTTP request > hide loading component.

import { HttpClient } from '@angular/common/http';
import { LoadingController } from '@ionic/angular';
import { from } from 'rxjs';
....
  ngOnInit() {
    from(this.presentLoading())
    .subscribe(() => {
      this.http.get(url) 
      .subscribe(
        (data) => {
          console.log(data);
        },
        (error) => {
          console.log(error);
        }
      )
      .add(() => this.loading.dismiss());
    });
  }

  private async presentLoading(): Promise<any> {
    this.loading = await this.loadCtrl.create({
      message: 'Please wait ...',
    });
    return await this.loading.present();
  }
}

This is working and it solved my problem but i want to know if my solution is correct and if there is a better way to do it.

Related: (None of the solutions there worked for me)
https://forum.ionicframework.com/t/dismiss-a-loadingcontroller/141148
https://github.com/ionic-team/ionic/issues/15109

Ionic:

   ionic (Ionic CLI)             : 4.9.0 (/usr/lib/node_modules/ionic)
   Ionic Framework               : @ionic/angular 4.0.2
   @angular-devkit/build-angular : 0.12.4
   @angular-devkit/schematics    : 7.2.4
   @angular/cli                  : 7.2.4
   @ionic/angular-toolkit        : 1.4.0

System:

   NodeJS : v11.7.0 (/usr/bin/node)
   npm    : 6.7.0
   OS     : Linux 4.4

I really appreciate any comments you can provide.

#2

I use a generic helper function, which can wrap any Observable. It looks like this:

    public wrapLoading<T>(source: Observable<T>): Observable<T> {
        let loader: any;

        const obs = from(this.loadingController.create({
            message: 'Please wait ...'
        }));

        const wrapper = obs.pipe(
            tap(loader2 => {
                loader = loader2;
                loader2.present();
            }),
            flatMap(() => source),
            finalize(() => {
                loader.dismiss();
            })
        );

        return wrapper;
    }

It’s basically the same thing you are doing. Then I can call it with any observable, and it will show a loading animation, while the observable is running:

this.guiHelper.wrapLoading(this.http.get(url)).subscribe(...);

Note, that you don’t have to nest multiple subscribe() calls. It’s better to pipe together a chain. Usually only the outer most user is calling subscribe().

Regards,
Norbert

PS: edited it to use generics in order for the type to be preserved

#3

Thank you so much @nharrer

I was looking for a solution like abstracting loading component creation and dismissing to another function and definitely it helped me.

Regards.
Irving