【问题标题】:Angular 2 Http Observable subscribe callback functionAngular 2 Http Observable 订阅回调函数
【发布时间】:2016-12-12 14:15:55
【问题描述】:

我的 .subscribe 函数有问题。 首先,我有一个向服务器发送请求的功能。就是这样。

protected sendRequest(data:string,url:string):Observable<any>{

    let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
    let options = new RequestOptions({ headers: headers });

    //let body = 'email=' + 'email' + '&password=' + 'password';
    return this.http.post(url, data, options).map(response => response.json());
}

现在 user.service 将 sendResquest 委托给这个文件,我已经在 user.service 中注入了 server.service 等等。

public login(email:string, password:string):Observable<any>{
    //format data to send
    let data:string = 'email=' + email + '&password=' + password;
    //let body = 'email=' + 'email' + '&password=' + 'password';

    let serverReturn:Observable<any> = this.sendRequest(data,"server/request/signin.php");
    //Log the server return
    //console.log(serverReturn);

    serverReturn.subscribe(
        //set the token and session elements of a logged user
        function(data){
            //console.log(data);
            //console.log(data.isSigned);
            if(data.isSigned == "true"){
                sessionStorage.setItem("isSigned","true");
                sessionStorage.setItem("userToken", data.userToken);
            } else if(data.userBlocked == "true"){
                sessionStorage.setItem("isSigned", "false");
            } else {
                sessionStorage.setItem("isSigned", "false");
            }
        }
    );
    return serverReturn;
}

现在我想要的是在 componentLogin 中获取这个 serverReturn,所以我必须知道根据这个调用的响应要做什么。 但是来自 .subscribe 的回调似乎无法访问此类的属性。 我正在关注这个answer 在那里我了解到:

通常,您从成功回调中获取结果并将其分配给您的变量。

最后这是我的登录组件,它从 user.service 调用登录

import { Component, ElementRef, ViewChild } from '@angular/core';
import { ModalComponent } from '../../ui/modal/modal.component';

import { UserService } from '../../utils/user.service';

@Component({
selector: 'login',
templateUrl: 'app/system/login/tpl.html',
styleUrls: ['app/system/login/style.css'],
directives: [ModalComponent],
providers: [UserService]
})
export class LoginComponent {
constructor(private userService:UserService, private elementRef:ElementRef){

}
private result:Array<any>;
@ViewChild(ModalComponent) modal:ModalComponent;
private signin():void{

    let email:string =  this.elementRef.nativeElement.querySelector("#email").value;
    let password:string = this.elementRef.nativeElement.querySelector("#password").value;

    this.userService.login(email, password).subscribe(data => this.result = data);
    console.log(this.result);

    //this.modal.showModal('Login ','Login');
}
}

问题是我尝试在成功回调中执行的任何变量或更改都会得到未定义的返回。如果我调用一个方法,订阅中的任何方法也会给我一个错误。 例如,如果我尝试这样做。

this.userService.login(email, password).subscribe(
        function(data){
            this.modal.showModal('Login ','Login');
        }
    );

我收到一个错误:

EXCEPTION: TypeError: Cannot read property 'showModal' of undefined

我做错了什么?我将尝试将结果设置为类变量。为什么我在订阅回调函数中调用的所有内容似乎都未定义? 我会很感激这方面的任何帮助。谢谢。

【问题讨论】:

  • 当你使用'function'时,它会改变内部this的值。尝试使用 lambda,即 data =&gt; this.modal.showmodal('Login ','Login')
  • 这确实适用于调用 showmodal 方法。但是,如果我尝试使用响应数据data =&gt; this.result = data 设置变量,我仍然会在控制台中得到一个未定义的结果。为什么?
  • 对于调试,设置一个窗口变量并将其记录到您收到错误的控制台:window['mythis'] = this; console.log(this); 在订阅之前尝试在您的函数中设置一个局部变量并记录(或使用它)即var self = this; 然后在你的回调中self.result = data;
  • 我发现了问题所在。发生这种情况是因为这是一个异步代码,那么如果您在订阅之前记录一个变量,代码将继续运行,并且只有在响应完成时才会执行成功回调。但是,当执行订阅后的代码时,结果将是“未定义”。感谢您的建议和更多的研究,现在我知道是什么原因造成的。问题是:如何确保只有在数据已全部收到时才执行某些代码?我无法传递未定义的值,然后等待服务器响应。
  • 您需要在回调中执行该代码才能使用数据。如果您希望能够让其他组件或服务访问它,那么您可以创建自己的 observable 并将其返回,然后在回调中为该 observable 提供一个值,该值会将其发送给任何订阅者。这似乎就是您对userService.login 所做的事情。你能举一个更清楚的例子说明你想做但不能做的事情吗?

标签: javascript http angular callback


【解决方案1】:

正如 Jason Goemaat 已经提到的,您需要使用 lambdas 来访问类属性。

在调试器中看不到它们的原因是在转译代码中this 被分配给_this。 你会看到一行

var _this = this;

其余的 lambda _this 被使用。这就是调试器不知道 lambda 中的任何 this. 变量的原因。

以 WebStorm 为例。该 IDE 附带一个调试器,该调试器可以识别该问题并自动对其进行补偿。但是,它仅适用于 chrome,因为它依赖于 chrome 插件。

【讨论】:

  • 如果我使用 lambda,它应该可以正常工作吗?但即使在这种情况下,data =&gt; this.result = data 的代码也不起作用。我应该可以访问类属性。我不知道该特定操作中发生了什么,如果我在订阅之外记录this.result,我仍然会收到未定义的错误。但现在我也可以使用模态和其他方法了。这就是现在的问题。
猜你喜欢
  • 1970-01-01
  • 2023-03-11
  • 2016-10-28
  • 2021-12-23
  • 2018-07-22
  • 2017-03-24
  • 2017-04-17
  • 2018-01-17
  • 2018-08-18
相关资源
最近更新 更多