Angular 无法将 http 返回结果赋值给变量

Angular fails to assign http returned result to the variable

我正在尝试使用 ionic2 + angular2 制作一个应用程序,但我无法从服务器 api.

获取帐户验证结果(0:失败 1:success)

这是结果代码class

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);
  }

这是登录页面代码

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。

我可以得到结果

result == 0 from console, if i print it inside the .then()

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

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

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

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

控制台打印 result == undefined 的原因是因为在 login() 中您正在使用 authenticate() 进行异步调用。 虽然这是运行ning,但程序其余部分的执行会继续到console.log()。因为 console.log() 执行速度比使用 authenticate() 发出网络请求快得多,所以它打印未定义,尽管后来 this.resultCode 中的值实际上是 0。

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

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

现在,由于您有调用异步 authenticate() 的同步函数 login(),您可能想做一些事情,但 仅在 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
    };
}

现在,在登录页面代码的任何其他地方,如果您希望 运行 您确定在完全登录后执行的代码,您可以这样做:

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