我具有以下TS功能:
CheckRegUser(u: User): boolean {
let b: boolean = true;
let toSend = {
email: u.email
};
this.http.post("http://localhost:8080/", toSend).subscribe((data: Valid) => {
if(!data.validity){
b = false;
}
});
console.log(b);
return b;
}
在这里,我正在连接到ExpressJS后端,并且返回了布尔结果。这部分工作正常,但问题是在“ this.http”中更改b的值之前执行了“ return b”语句,因此无论Express的响应如何,b始终为真。 >
我知道TS和JS是异步的,因此引起此问题,但是我找不到解决我问题的正确方法。任何帮助,将不胜感激。
答案 0 :(得分:3)
您可以尝试使用async await
async CheckRegUser(u: User): Promise<boolean> {
let toSend = {
email: u.email
};
let k = await this.http.post("http://localhost:8080/", toSend).subscribe((data: Valid){
let b: boolean = true;
if(!data.validity){
b = false;
}
return b
});
console.log(k);
return k;
}
答案 1 :(得分:2)
当我刚开始使用Google Maps应用程序学习Observables / Reactive编程时,我也遇到了这个常见问题:D!
发现,您意识到异步函数尚未同步b
(默认为b
)时突变了true
布尔标志;
要解决此问题,重组函数以将Observable
返回给调用方可能更容易。
并可能查找Observable
链接或类似概念的Promise
链接。
旧示例:
CheckRegUser(u: User): boolean {
const b: boolean = true;
const toSend = {
email: u.email
};
const httpPost: Observable<aJsonObject> = this.http.post("http://localhost:8080/", toSend)
const httpPostSubscription: Subscription = httpPost
.subscribe((data: Valid) => { // This is asynchronous
if (!data.validity) {
b = false;
}
});
console.log(b);
return b; // This is effectively sync returning your default value `b = true`;
}
最好重命名变量以使其更清晰。
b
或isDataValid
。
最好以const
变量开头的函数样式,以帮助避免可变性问题。
如果您更熟悉Promises
,也可以尝试promisify
httpClient.post Observable。
一般的要旨是将Observable
返回给呼叫者,然后在其中.subscribe
。
当某些内容异步返回时,您应该将异步性一直返回到顶部。
重构代码以反映这些做法
CheckRegUser(user: User, httpClient: HttpClient): Observable<Valid> {
// 1. Data to send
type EmailPost = { email: string }
const emailJsonToSend: EmailPost = { // I prefer explicit typing wherever possible :tada: :D
email: user.email
};
// 2. POST the data to the web server
const emailHttpPostObs: Observable<Valid> = httpClient.post("http://localhost:8080/", emailJsonToSend);
return emailHttpPostObs;
}
CallerSubmitUserFunction(user: User, httpClient: HttpClient) {
// Made some assumptions, please comment and we can work out a better solution
// Explicitly typed things as an example.
// 1. You have a user e.g. new User(name:'myUser', email: 'myEmailAddressOrEmailContent@email.com');
const userToSend: User = user;
// 2. You POST the user.email and get response.
const validatedUserDataObs: Observable<Valid> = CheckRegUser(userToSend, httpClient);
// 3. You check whether the server accepted the data and whether it was valid.
const validatedUserDataObs: Subscription = validatedUserDataObs
.subscribe((data: Valid) => {
// Perform data validation or Error checking here.
// If data is valid,
if (dataValidationFunction()) {
// Do something here
// Instead of trying to return the boolean in the asynchronouse function.
// Directly do something after the server responds (whenever it happens).
}
}) // catch Error
// It would also be better if you could rename your variables to be more self-indicative
// var dataIsValid
}