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