Return value with asynchronous functions in Typescript
You can try with 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;
}
I had this common problem when I was just starting to learn Observables/Reactive programming with a Google Maps app as well :D!
Spot on, you realised that asynchronous function hasn't mutated the b
boolean flag yet when the function synchronously returns b
(that defaulted to true
);
To fix this it might be easier to restructure your function to return the Observable
to the caller.
and maybe look up Observable
chaining or similar concept Promise
chaining.
Old example:
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`;
}
It would be better if you could rename your variables to be clearer.
b
or isDataValid
.
Might also be good practice to start functional-style with const
variables to help avoid mutability issues.
If you're more familiar with Promises
, you could also try to promisify
the httpClient.post Observable.
General gist of it is to pass the Observable
back to the caller and .subscribe
it there.
When something is returning asynchronously, you should return the asynchronicity all the way back to the top.
Refactor code to reflect these practices
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: '[email protected]');
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
}