Home > Software design >  Method is not returning the correct value passed from observable subscription. (Angular 14)
Method is not returning the correct value passed from observable subscription. (Angular 14)

Time:09-17

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

  • Related