Tavish Aggarwal
Tavish Aggarwal

Reputation: 1060

How to handle two calls and the loading controller in Ionic 4

I have a requirement where I have 2 API calls, and I want the first two calls to be there for the first request. And 2nd API call to be there when navigated back. I am calling 1st API in ngOnInit webhook and 2nd API on ionViewWillEnter webhook.

The issue which I am facing is sometimes my loader doesn’t get dismissed when both of the request complete at the same time.

So the possible solution which I am thinking is that if I could call both APIs on the first load synchronously and thereafter call another API every time the back button is clicked.

NOTE: I am using loaders in my interceptor.

CODE: For interceptor

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        // Clone the request to add the new header.
        const authReq = req.clone();
        this.showLoading();

        // send the newly created request
        return next.handle(authReq).pipe(catchError((error) => {
            if (error.status === 401) {
                this._navCtrl.navigateForward('/login');
            }
            return throwError(error);
        }), finalize( () => {
            console.log('hi');
            this.dismissLoading();
          })
        );
    }

EDIT:

Code to show loader and hide loader:

    async showLoading() {
        return await this._loadingCtrl.create().then(a => {
            a.present();
        });
    }

    async dismissLoading() {
        return await this._loadingCtrl.dismiss();
    }

Upvotes: 1

Views: 4462

Answers (3)

Charlie
Charlie

Reputation: 69

   private loading: HTMLIonLoadingElement;
     constructor(public loadingController: LoadingController) { }

     public async show(): Promise<void> {
       return await this.loadingController.create({
         message: 'Please wait...',
         spinner: 'crescent'
       }).then(a => {
         a.present().then(() => {
           console.log('presented');
         });
       });
     }

       return await this.loadingController.dismiss().then(() =>               
    console.log('dismissed'));
      }`enter code here`

Upvotes: 0

quangpdt
quangpdt

Reputation: 151

In my case, I will create a LoaderService to handle the Loading by myself. The special thing is I will create a flag called isShowing, so if the loading is already showing, we just need to update the loading message by calling presentLoader function again. There will be only one Loading popup show up on your screen.

In your case, I would not recommend to display the Loader in HTTP Interceptor because we cannot handle the HTTP call stack there. Just create a new function that combines all necessary API calls and show/dismiss popup when you start/finish processing the data.

import { LoadingController } from '@ionic/angular';
import { Injectable } from '@angular/core';

@Injectable()
export class LoaderService {
    private loading: HTMLIonLoadingElement;
    private isShowing = false;

    constructor(private loadingController: LoadingController) {}

    public async presentLoader(message: string): Promise<void> {
        if (!this.isShowing) {
            this.loading = await this.loadingController.create({
                message: message
            });
            this.isShowing = true;
            return await this.loading.present();
        } else {
            // If loader is showing, only change text, won't create a new loader.
            this.isShowing = true;
            this.loading.message = message;
        }
    }

    public async dismissLoader(): Promise<void> {
        if (this.loading && this.isShowing) {
            this.isShowing = false;
            await this.loading.dismiss();
        }
    }
}

Upvotes: 4

Varun Sukheja
Varun Sukheja

Reputation: 6516

  1. The simple solution would be to make a function call whenever you click the bak button and inside the function you can make a API call.
  2. Instead of linking to the back button you can use ionViewWillEnter, which is called whenever you are about to leave a page but the downside would be it is called every time view is changed regardless of the fact that only when back button is clicked.

Also you should check, is your service singleton and it creates a single instance of ionic-loader. I think in your case more than one instance of loader is being created.

Also instead of calling the loader in interceptor, you can call showLoading() in ionViewWillEnter and hideLoading() in ionViewDidEnter() of your page.

You can create a Singleton Loader Service as shown below. This service will take care of creating only a single instance of ionic loader.

import { Injectable } from '@angular/core';

import { LoadingController } from '@ionic/angular';

@Injectable({
    providedIn: 'root'
})
export class LoaderService {
    private loader: HTMLIonLoadingElement;

    constructor(private loadingController: LoadingController) {}

    async showLoader() {
        if (!this.loader) {
            this.loader = await this.loadingController.create({ message: 'Loading' });
        }
        await this.loader.present();
    }

    async hideLoader() {
        if (this.loader) {
            await this.loader.dismiss();
            this.loader = null;
        }
    }
}

Upvotes: 1

Related Questions