Home > Software design >  How to avoid to return an observable inside a promise
How to avoid to return an observable inside a promise

Time:01-02

I'm using AngularFire to manage user inside my app. I'm still learning about observables and rxjs.

I'm trying to call signInWithEmailAndPassword method - which return a promise - and to retrieve a doc from a collection.

In my service I get the document using this method:

getDbUser(uid): Observable<User> {
   return this.angularFirestore.collection<User>(USERS).doc(uid).valueChanges()
}

and I login user with:

login(user: User) {

    // sign in con email e password
    return this.angularFireAuth.signInWithEmailAndPassword(user.email, user.password)
      .then((result) => {

        if(result.user?.uid) {
        
          // get user doc
          return this.getDbUser(result.user.uid);
        }

        return null;
      });

  }

With this code, calling login method requires to solve a promise and then subscribe to the observable, like this:

this.userService.login(this.loginUser)
  .then((userObs) => {
      userObs.subscribe((user) => {
        console.log(user);
      });
  })

I would really like to avoid this but I'm not sure how to to do. I tried using RxJs toPromise operator:

login(user: User) {

    // sign in con email e password
    return this.angularFireAuth.signInWithEmailAndPassword(user.email, user.password)
      .then((result) => {

        if(result.user?.uid) {

          // recupero l'utente dal db
          return this.getDbUser(result.user.uid).toPromise();
        }

        return null;
      });

  }

but somehow this is not working (the promise is never resolved).

CodePudding user response:

if you want to let know of any obserable consumer that a user just logged in only after signInWithEmailAndPassword() has returend i would decalre a subject and subsscribe to user$ from any service consumers.

private userSubject$:Subject<string>=new Subject<string>();
public user$:Observable<string>=this.userSubject$.asObservable();
    login(user: User) {

    // sign in con email e password
    return this.angularFireAuth.signInWithEmailAndPassword(user.email, user.password)
      .then((result) => {

        if(result.user?.uid) {

          // recupero l'utente dal db
          return this.userSubject$.next(result.user.uid);
        }

        return null;
      });

} and from outside you will use the service :

this.userService.login(this.loginUser);
this.userService.user$.subscribe(user=>console.log);

CodePudding user response:

Try using rxjs operators like mergeMap , swtichMap , pipe , map etc .You can avoid nested subscription with those.

  • Related