Reputation: 21
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<boolean>
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);
}
Upvotes: 0
Views: 258
Reputation: 1
/* How about you use promise */
checkUsernameExists(username: string): Promise<any> {
return new Promise<any>((resolve, reject) => {
this.getUser('[email protected]')
.subscribe(
async (result: any) => {
if(result)
{
console.log('result: ', result);
resolve(result)
}
else if(result && result.IsError)
{
console.log('result: ', result);
reject(result.Error)
}
},
(err) => {
reject(err)
});
});
}
/* To Call this Method => Do what you want to do with the result */
await checkUsernameExists("Your_Username").then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
Upvotes: 0
Reputation: 1126
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
Upvotes: 2