У меня была эта общая проблема, когда я только начинал изучать Observables / Reactive программирования с помощью приложения Google Maps: 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
}