When I first started learning about Observables and Reactive programming with a Google Maps app, I encountered this common issue!
You correctly identified that the asynchronous function had not yet updated the b
boolean flag when the function synchronously returned b
(which was initially set to true
);
To resolve this, it may be helpful to restructure your function so that it returns the Observable
to the caller.
You might want to explore concepts like Observable
chaining or similar approaches used in Promise
chaining.
Previous 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's advisable to use clearer variable names like b
or isDataValid
.
You could also consider starting with functional-style coding using const
variables to avoid mutability issues.
If you are more comfortable with Promises
, you can try converting the httpClient.post Observable into a promise using promisify
.
The key idea is to pass the Observable
back to the caller and handle it using .subscribe
there.
Ensure that asynchronous responses are propagated all the way to the top of the process.
Revise the code following these best practices
CheckRegUser(user: User, httpClient: HttpClient): Observable<Valid> {
// 1. Data to send
type EmailPost = { email: string }
const emailJsonToSend: EmailPost = {
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) {
// Some assumptions were made for demonstration purposes, feel free to provide feedback for improvements
// Variable types have been explicitly defined as an example.
const userToSend: User = user;
const validatedUserDataObs: Observable<Valid> = CheckRegUser(userToSend, httpClient);
const validatedUserDataObs: Subscription = validatedUserDataObs
.subscribe((data: Valid) => {
// Implement data validation or Error handling here.
// If data is valid,
if (dataValidationFunction()) {
// Perform necessary actions here
// Instead of trying to return the boolean within the asynchronous function.
// directly handle operations after the server responds.
}
}) // catch Error
// Consider renaming variables for better clarity
// var dataIsValid
}