Angular 2 Http Observable 订阅回调函数

3

我在使用.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将sendRequest委托给此文件,我已经在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的回调似乎无法访问此类的属性。 我正在遵循这个 答案。 我从那里学到:

通常,您会将成功回调的结果分配给您的变量。

最后,这是我的登录组件,它调用用户服务中的登录功能。

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

I get an error:

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

我哪里做错了?我试图将结果设置为一个类变量。为什么我在subscribe回调函数中调用的所有内容似乎都是未定义的? 非常感谢您的帮助。谢谢。


当您使用“function”时,它会更改其内部的this值。尝试使用lambda,即data => this.modal.showmodal('登录','登录') - Jason Goemaat
这确实可以调用showmodal方法。但是,如果我尝试使用响应数据data => this.result = data设置变量,仍然会在控制台中得到未定义的结果。为什么? - David Vale
调试时,设置一个 window 变量并将其记录到控制台,在您收到错误的位置:window ['mythis'] = this; console.log(this); 尝试在订阅之前在函数中设置一个本地变量,并记录该变量(或使用它),例如:var self = this; 然后在回调中 self.result = data; - Jason Goemaat
我找到了问题所在。这是由于这是异步代码,如果在订阅之前记录变量,则代码将继续运行,并且仅在响应完成时执行成功回调。但是,当订阅后的代码执行时,结果将为“未定义”。感谢您的建议和更多的研究,现在我知道是什么原因导致了这个问题。现在的问题是:如何确保只有在数据已经接收到的情况下才执行某些代码?我不能传递未定义的值,然后等待服务器响应。 - David Vale
你需要在回调函数中执行该代码以使用数据。如果你想让其他组件或服务能够访问它,那么你可以创建自己的可观察对象并返回它,然后在回调函数中为该可观察对象提供一个值,这将发送给任何订阅者。这似乎是你正在使用 userService.login 的方式。你能否给出一个更清晰的例子,说明你想做但无法做到的事情? - Jason Goemaat
我会更新问题。 - David Vale
1个回答

0
正如Jason Goemaat所提到的,您需要使用lambda表达式来访问类属性。
之所以在调试器中看不到它们,是因为在转换后的代码中,this被赋值给了_this
您将会看到一行
var _this = this;

对于 lambda 函数的其余部分,使用 _this。这就是为什么调试器不知道 lambdas 中的任何 this. 变量。

例如,请尝试使用 WebStorm。该 IDE 配备了一个调试器,它知道这个问题并自动进行了补偿。但是,它仅适用于 Chrome,因为它依赖于 Chrome 插件。


如果我使用lambda,它应该可以工作,对吧?但即使在这种情况下,data => this.result = data的代码也不起作用。我应该可以访问类属性。我不知道在特定操作中发生了什么,如果我在subscribe之外记录this.result,我仍然会得到未定义的错误。但现在我也可以访问modal和其他方法。这就是问题所在。 - David Vale

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接