Angular无法将http返回结果分配给变量

时间:2017-06-07 17:37:24

标签: angular ionic-framework ionic2 hybrid-mobile-app

我正在尝试使用ionic2 + angular2创建应用程序,我无法从服务器API获取帐户验证结果(0:失败1:成功)。

这是ResultCode类

export class ResultCode{
  result: number;
}

这是服务代码

@Injectable()
export class LoginService{
  private headers = new Headers({'Content-Type': 'application/json'});
  constructor(private http:Http){ }

  authenticate(url:string,email:string, password:string): Promise<ResultCode>{
    return this.http
      .get(url)
      .toPromise()
      .then(res => res.json() as ResultCode)
      .catch(this.handleError);
  }
  private extractData(res: Response) {
    let body = res.json();
    return body.result || { };
  }
  private handleError (error: Response | any) {
    // In a real world app, you might use a remote logging infrastructure
    let errMsg: string;
    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
    } else {
      errMsg = error.message ? error.message : error.toString();
    }
    console.error(errMsg);
    return Observable.throw(errMsg);
  }

这是LoginPage代码

export class LoginPage {
  resultCode:ResultCode;

  private loginForm : FormGroup;
  constructor(
   public navCtrl: NavController,
   private loginService:LoginService,
   private formBuilder: FormBuilder) {
    this.loginForm = this.formBuilder.group({
     email: ['',[Validators.required,Validators.email]],
     password: ['',[Validators.required,Validators.minLength(6)]]
    });

  }
  login(){
   let email = this.loginForm.get('email').value;
   let password = this.loginForm.get('password').value;
   let url = `https://www.xxxx.com/api.pl?fn=login&email=${email}&password=${password}`;
   this.authenticate(url,email,password);
   console.log("result == " + this.resultCode.result);

  }
  authenticate(url,email,password){
    this.loginService.authenticate(url,email,password)
    .then(result=> this.resultCode = result);
  }

}

我从控制台得到结果== undefined。

我可以得到结果

  

结果== 0   从控制台,如果我在.then()

内打印
  authenticate(url,email,password){
    this.loginService.authenticate(url,email,password)
    .then(result=> console.log("result == " + result.result));
  }

我想知道在authenticate()函数完成之前是否执行了console.log?谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

让我们仔细看看我们的代码:

login() {
   //...
   this.authenticate(url,email,password);
   console.log("result == " + this.resultCode.result);
   //...
}

控制台打印result == undefined的原因是因为在login()内部,您正在使用authenticate()进行异步调用。 运行时,程序其余部分的执行一直持续到console.log()。因为console.log()的执行速度比使用authenticate()发出网络请求要快得多,所以它打印未定义,但稍后this.resultCode内的值实际为0。

为了在程序中稍后处理响应,您必须等到它到达。因此,在网络请求完成后,您想要做的任何事情都需要在.then()函数的authenticate()部分内进行编码,如下所示:

authenticate (url,email,password){
    this.loginService.authenticate(url,email,password)
        .then((result) => {
           // NOW WE ARE ALWAYS SURE THE RESPONSE HAS ARRIVED
           this.resultCode = result
        });
}

现在,由于你有同步函数login()调用异步authenticate(),你可能只想在 login()和之后做一些事情。

执行此操作的最佳方法是使用Promises。这就是我改变你的代码以支持它的方式:

login(){
   let email = this.loginForm.get('email').value;
   let password = this.loginForm.get('password').value;
   let url = `https://www.xxxx.com/api.pl?fn=login&email=${email}&password=${password}`;

   return new Promise((resolve, reject) => { // notice we now return a Promise here too
       this.authenticate(url,email,password)
           .then(result){
                this.resultCode = result;
                resolve (result);
           }
    };
}

authenticate(url,email,password){
    return new Promise((resolve, reject) => { // notice we now return a Promise
        this.loginService.authenticate(url,email,password)
            .then((result) => { resolve(result)); } // notice the change here, resolving the value outwards to the caller
    };
}

现在,在您的LoginPage代码中的任何其他位置,您希望运行完全登录后确定执行的代码,您可以这样做:

login().then(){
    // NOW WE ARE SURE LOGIN HAS COMPLETED
}