无法在Subscribe()的错误响应中关闭LoadingController-离子4

时间:2019-03-08 08:22:41

标签: javascript angular typescript ionic-framework ionic4

当用户尝试登录时,我正在显示一个LoadingController。同时,正在调用一个API。

当我从订阅中获得SUCCESS响应时,我可以关闭LoadingController,但是当我收到ERROR响应时,则无法关闭。请帮忙!

我是一名专业的Python开发人员,并且是Ionic的新手,这是一天前才开始的。因此,请提供协助。

import { Component, OnInit } from '@angular/core';
import { ToastController, LoadingController } from '@ionic/angular';

import { CallapiService } from '../callapi.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.page.html',
  styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {

  userEmail = '';
  userPassword = '';
  loginUrl = 'login/';
  loginMethod = 'POST';
  postBody = {};


  constructor(
    public toastController: ToastController,
    public loadingController: LoadingController,
    private callApiService: CallapiService,
  ) { }

  ngOnInit() {
  }

  async presentToast(displayMessage) {
    const toast = await this.toastController.create({
      message: displayMessage,
      duration: 2000,
      position: 'middle',
    });
    return await toast.present();
  }

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


  loginUser() {
    if (this.userEmail === '' || this.userPassword === '') {
      this.presentToast('Email and password are required.');
    }

    else {
      this.presentLoading('Processing...');
      this.postBody = {
        email: this.userEmail,
        password: this.userPassword,
      };
      this.callApiService.callApi(this.loginUrl, this.postBody, this.loginMethod).subscribe(
        (success) => {
          console.log(success);
          this.loadingController.dismiss();
        },
        (error) => {
          console.log(error);
          this.loadingController.dismiss();
        }
      );
      this.loadingController.dismiss();
    }

  }

}

4 个答案:

答案 0 :(得分:1)

没有任何服务,

使用Ionic 4加载控制器时遇到相同的问题。 经过反复试验,我得到了可行的解决方案。

由于加载控制器功能正在使用async和await,因为它们都是异步功能。

dismiss()函数将在present()函数之前调用,因为dismiss函数不会等到创建并显示加载程序时才执行,它将在present()函数调用前立即触发。

下面是有效代码,

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

   presentLoading() {
     if (this.loading) {
       this.loading.dismiss();
     }
     return new Promise((resolve)=>{
       resolve(this.loadingController.create({
        message: 'Please wait...'
      }));
     })
   }

  async dismissLoading(): Promise<void> {
    if (this.loading) {
      this.loading.dismiss();
    }
  }

  someFunction(){
    this.presentLoading().then((loadRes:any)=>{
      this.loading = loadRes
      this.loading.present()

      someTask(api call).then((res:any)=>{
        this.dismissLoading();
      })
    })
  }

答案 1 :(得分:0)

this.callApiService.callApi(this.loginUrl, this.postBody, this.loginMethod)
  .subscribe(
    (data) => {
      // Called when success  
    },
    (error) => {
      // Called when error
    },
    () => {
      // Called when operation is complete (both success and error)
      this.loadingController.dismiss();
    });

来源:https://stackoverflow.com/a/54115530/5442966

答案 2 :(得分:0)

使用Angular属性绑定。创建要加载的组件:

import { Component, Input } from '@angular/core';
import { LoadingController } from '@ionic/angular';

@Component({
  selector: 'app-loading',
  template: ''
})
export class LoadingComponent {
  private loadingSpinner: HTMLIonLoadingElement;

  @Input()
  set show(show: boolean) {
    if (show) {
      this.loadingController.create().then(loadingElem => {
        this.loadingSpinner = loadingElem;
        this.loadingSpinner.present();
      });
    } else {
      if (this.loadingSpinner) {
        this.loadingSpinner.dismiss();
      }
    }
  }

  constructor(private loadingController: LoadingController) {}
}

...然后在“ login.page.html”中使用您的组件:

...    
<app-loading [show]="showLoading"></app-loading>

...在“ LoginPage”中创建一个属性“ showLoading”,并将其设置为true或false:

//.... some source code
export class LoginPage implements OnInit {
  showLoading;
  userEmail = '';
  userPassword = '';
  loginUrl = 'login/';
  loginMethod = 'POST';
  postBody = {};

  //.... some source code

  loginUser() {
    if (this.userEmail === '' || this.userPassword === '') {
      this.presentToast('Email and password are required.');
    } else {
      this.showLoading = true;
      this.postBody = {
        email: this.userEmail,
        password: this.userPassword
      };
      this.callApiService
        .callApi(this.loginUrl, this.postBody, this.loginMethod)
        .subscribe(
          success => {
            console.log(success);
            this.showLoading = false;
          },
          error => {
            console.log(error);
            this.showLoading = false;
          }
        );
      this.showLoading = false;
    }
  }
}

这对我有用,我在其他页面上重复使用了加载组件!

推荐阅读:https://angular.io/start

答案 3 :(得分:0)

我实际上遇到了这个确切的问题,对我来说,答案只是使用await

用于创建和解除加载程序的函数均返回promise。我意识到发生的事情是,订阅/承诺拒绝使所有其他承诺无法完成。现在,我只是在等待演讲和辞退,我没有问题:

async getData() {  
  //await presenting
  await this.presentLoading('Loading...');

  try {
    let response = await this.httpService.getData();
    await this.loadingController.dismiss();

    //...
  catch(err) {
    this.loadingController.dismiss();
    //handle error
    //...
  }
}

async presentLoading(msg: string) {
  const loading = await this.loadingController.create({
    spinner: 'crescent',
    message: msg
  });
  await loading.present();
}

我希望这个简单的解决方案有帮助!