So....
I'm trying to validate from an api (angular's in memory api) that a user exists given a username. The function checkUsernameExists(username)
returns an observable based on whether the api returns undefined or a user object. I'm having an issue that regardless of the username (existing or not existing) it always returns false. I know that getUser()
functions correctly as it returns undefined when a user doesn't exists and the user object when it does.
Preferably would only like to adjust the checkUsernameExists
function if possible. This function is used for a (working) async validator. I've looked up all over how to solve this type of thing but can't find anything that isn't deprecated or fits what I need in order for it work properly.
usersUrl = '/api/users';
constructor(private http: HttpClient) {}
users = this.http.get<User[]>(this.usersUrl).pipe(shareReplay());
// gets a user object when subscribed to
getUser(username: string): Observable<User | undefined> {
return this.users.pipe(
take(1),
map((users: User[]) => {
return users.find((user) => user.username === username);
})
);
}
// check if user exists
checkUsernameExists(username: string): Observable<boolean> {
var userValid = false;
this.getUser('[email protected]')
.pipe(take(1)).subscribe(
result => {
if (result === undefined) {
console.log('result: ', result);
return (userValid = false);
} else {
console.log('result: ', result);
return (userValid = true);
}
}
);
console.log(userValid) // no matter the username, the value is always the same as its initialization (false)
return of(userValid);
}
I know this has to be an async issue or something and am still very new to Rxjs and Angular. Any help or input would be appreciated. If you need more code from me or have questions in order to provide better input please feel free to ask!
If you are able to reply if you could help explain a little bit of why you provided your answer that would be super helpful and awesome! THANK YOU IN ADVANCE
CodePudding user response:
your order of operations is the the problem in checkUserNameExists
method
you must wait for the observable to complete. but your code is making call to an observable this.getUser
and then immediately returning return of(userValid)
.
since the observable has not completed, the vale of userValid is stil the default false
. which is the behavior you described
Update your method to
checkUsernameExists(username: string): Observable<boolean> {
return this.getUser('[email protected]').pipe(
.map( (result: any) => {
if (result === undefined) {
console.log('result: ', result);
return (userValid = false);
} else {
console.log('result: ', result);
return (userValid = true);
}
})
);
}
this ensures that the userValid
is only returned when the observable has completed.
and is also removes the need for double susbscription