Ionic 4: "Loading Controller" dismiss() is called before present() which will keep spinner without dismissing

rami bin tahin picture rami bin tahin · Sep 30, 2018 · Viewed 44.6k times · Source

I used "Ionic Loading Controller" to show a spinner until the data is retrieved then it calls "dismiss()" to dismissed it. it works fine, but sometimes when the app already have the data, the "dismiss()" is called before the "create()" and "present()" is done which will keep the spinner without dismissing...

I tried to call the data inside "loadingController.present().then()", but that caused the data to be slower...

is this a bug? how to solve the this issue?

Example of my code:

customer: any;

constructor(public loadingController: LoadingController, private customerService: CustomerService)

ngOnInit() {
  this.presentLoading().then(a => consloe.log('presented'));
  this.customerService.getCustomer('1')
  .subscribe(customer => {
    this.customer = customer;
    this.loadingController.dismiss().then(a => console.log('dismissed'));
  }
}

async presentLoading() {
  const loading = await this.loadingController.create({
    message: 'wait. . .',
    duration: 5000
  });
  return await loading.present();
}

Answer

rami bin tahin picture rami bin tahin · Oct 24, 2018

this is how I solved my issue..

I used a boolean variable "isLoading" to change to false when dismiss() is called. after present() is finished if "isLoading" === false (means dismiss() already called) then it will dismiss immediately.

also, I wrote the code in a service so I don't have to write it again in each page.

loading.service.ts

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

@Injectable({
  providedIn: 'root'
})
export class LoadingService {

  isLoading = false;

  constructor(public loadingController: LoadingController) { }

  async present() {
    this.isLoading = true;
    return await this.loadingController.create({
      // duration: 5000,
    }).then(a => {
      a.present().then(() => {
        console.log('presented');
        if (!this.isLoading) {
          a.dismiss().then(() => console.log('abort presenting'));
        }
      });
    });
  }

  async dismiss() {
    this.isLoading = false;
    return await this.loadingController.dismiss().then(() => console.log('dismissed'));
  }
}

then just call present() and dismiss() from the page.

the example in question:

customer: any;

constructor(public loading: LoadingService, private customerService: CustomerService)

ngOnInit() {
  this.loading.present();
  this.customerService.getCustomer('1')
  .subscribe(
    customer => {
      this.customer = customer;
      this.loading.dismiss();
    },
    error => {
      console.log(error);
      this.loading.dismiss();
    }
  );