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

前端 未结 20 2213
逝去的感伤
逝去的感伤 2020-12-08 01:06

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 alre

相关标签:
20条回答
  • 2020-12-08 01:33

    I had the same problem, apparently I figured It out by identifying the problem first. This problem occurs when the duration of that Loader got expired so it basically got dismissed without our full control..

    Now, It will work fine Until you are also using dismiss() MANUALLY.

    So if you are going to use dismiss() manually with duration, remove the duration on create. then use setTimeout() perhaps

    // create loader
    this.loader = this.loadingCtrl.create()
    
    // show loader
    this.loader.present().then(() => {})
    
    // add duration here
    this.loaderTimeout = setTimeout(() => {
        this.hideLoader()
    }, 10000)
    

    then create your hide loader here

    // prepare to hide loader manually
    hideLoader() {
       if (this.loader != null) {
          this.loader.dismiss();
          this.loader = null
        }
    
        // cancel any timeout of the current loader
        if (this.loaderTimeout) {
          clearTimeout(this.loaderTimeout)
          this.loaderTimeout = null
        }
    }
    
    0 讨论(0)
  • 2020-12-08 01:34

    Here's how I've solved the same issue in my project. I use this service in the HTTP Interceptor to show the loader for all the REST API calls inside my app.

    loading.service.ts

    import {Injectable} from '@angular/core';
    import {LoadingController} from '@ionic/angular';
    
    @Injectable({
      providedIn: 'root'
    })
    export class LoadingService {
      constructor(public loadingController: LoadingController) {
      }
    
      async present(options: object) {
        // Dismiss all pending loaders before creating the new one
        await this.dismiss();
    
        await this.loadingController
          .create(options)
          .then(res => {
            res.present();
          });
      }
    
      /**
       * Dismiss all the pending loaders, if any
       */
      async dismiss() {
        while (await this.loadingController.getTop() !== undefined) {
          await this.loadingController.dismiss();
        }
      }
    }
    

    In the original question context this could be used like below:

    ...
    import {LoadingService} from '/path/to/loading.service';
    ...
    customer: any;
    
    constructor(public loadingService: LoadingService, private customerService: CustomerService)
    
    ngOnInit() {
      this.loadingService.present({
        message: 'wait. . .',
        duration: 5000
      });
      this.customerService.getCustomer('1')
      .subscribe(customer => {
        this.customer = customer;
        this.loadingService.dismiss();
      }
    }
    
    0 讨论(0)
  • 2020-12-08 01:34

    The simple way is Add setTimeOut function :

    setTimeout(() => {
          this.loading.dismiss();
        }, 2000);
    
    0 讨论(0)
  • 2020-12-08 01:35

    My solution for this problem, was to set a status variable. Here it is:

    @Injectable()
        export class LoaderSerive {
        private status: 'pending' | 'dismissed' | 'present' = 'dismissed';
    
        constructor(public loadingCtrl: LoadingController) {}
    
        public show() {
            if (this.status === 'present') {
                this.hide();
            }
    
            this.status = 'pending';
    
            this.loadingCtrl.create({
                id: 'spoon-indicator-1',
                spinner: null,
                message: `
                    <div>
                        <div class="loading-indicator--position">
                            <div class="loading-indicator">
                                <div class="bowl">
                                    <div class="spoon"></div>
                                    <div class="bowl-content"></div>
                                </div>
                            </div>
                        </div>
                    </div>`,
                duration: 6000
            })
            .then((loader) => loader.present())
            .then(() => {
                if (this.status === 'pending') {
                    this.status = 'present';
                } else {
                    this.hide();
                }
            });
        }
    
        public hide() {
            this.loadingCtrl
                .dismiss(null, undefined, 'spoon-indicator-1')
                .catch((err) => Utilities.log('Loader error!', err))
                .then(() => this.status = 'dismissed');
        }
    }
    
    0 讨论(0)
  • 2020-12-08 01:37

    Ionic 5 - Simple and short, using setTimeout, setInterval is rather a workaround than a solution.

    In my case, I had presentLoading method async and dismissLoading method sync.. causing this issue.

    I just added async await to my dismissoading and it works fine perfectly. for safety switch of not having 'overlay don't exisit' error added a boolean only to dismiss if loader present

      async presentLoading() {
        this.loadingPresent = true;
        const loading = await this.loadingController.create({
          message: 'Loading...',
        });
        return await loading.present();
      }
    
      async dismissLoading() {
        if (this.loadingPresent) {
          await this.loadingController.dismiss();
        }
        this.loadingPresent = false;
      }
    
    0 讨论(0)
  • 2020-12-08 01:38

    This way it also resolved concurrent API call loader dismiss issue fix. You can call those functions to form the interceptor too. There is no fix duration, because if any call needs much time loader will continue. But if anyone gives duration then if that API won't stop by this time loader will stop

    import { Injectable } from '@angular/core';
    import { LoadingController } from '@ionic/angular';
    
    @Injectable({
      providedIn: 'root'
    })
    export class LoadingService {
      isLoading = false;
      loaderCounter = 0;
      loading: HTMLIonLoadingElement;
    
      constructor(public loadingController: LoadingController) {}
    
      async present() {
        this.loaderCounter = this.loaderCounter + 1;
    
        if (this.loaderCounter === 1) {
          this.isLoading = true;
          const { loadingDuration, loadingMessage = loadingDefaultOptions.loadingMessage, loadingCssClass } = options;
          this.loading = await this.loadingController.create({
            duration: loadingDuration,
            message: loadingMessage,
            cssClass: loadingCssClass
          });
          await this.loading.present();
        }
      }
    
      async dismiss() {
        this.loaderCounter = this.loaderCounter - 1;
        if (this.loaderCounter === 0) {
            this.isLoading = false;
            await this.loading.dismiss();
        }
      }
    }
    
    0 讨论(0)
提交回复
热议问题