Search code examples
angularfirebasepromiseobservablengrx

How do I return an Observable to an outer promise in Effects of NgRX?


I have a question of how to return an Observable to an outer promise. I have in my effects.ts the following:

  @Effect()
  login$: Observable<Action> = this.actions$.pipe(
    ofType(UserActions.LOGIN),
    switchMap((action: UserActions.LoginAction) => {

      this.db.auth.signInWithEmailAndPassword(action.payload.email, action.payload.password).then(data => {
        this.db.auth.currentUser.getIdToken().then(reply => {
          return this.http.post(environment.apiUrl+'/api/login', { token: reply }).subscribe(response => {
              if (response['valid'] === 'true') {
                localStorage.setItem('token', JSON.stringify(reply));
                this.router.navigate(['dash']);
              }
            });
        });
      }).catch(err => {
        console.log('signIn failed: ' + err.message);
      });
    })
  );

Now, my goal overall is to simply log in to FireBase to be able to grab an ID token and submit a post request to the back-end. If the response comes back with the property valid "true" then proceed to navigate to the "dash" module.

However, my problem is:

Argument of type '(action: UserActions.LoginAction) => void' is not assignable to parameter of type '(value: LoginAction, index: number) => ObservableInput'. Type 'void' is not assignable to type 'ObservableInput'.ts(2345)

I believe it is because I put my return statement within an outer promise. But I don't know how to make it return properly because Firebase uses promises, and NgRX uses Observables! I am trying to return an Observable from within a promise... thank you


Solution

  •   @Effect()
      login$: Observable<Action> = this.actions$.pipe(
        ofType(UserActions.LOGIN),
        switchMap((action: UserActions.LoginAction) =>
          from(this.db.auth.signInWithEmailAndPassword(action.payload.email, action.payload.password)),
        ),
        // switchMapTo(from(this.db.auth.currentUser.getIdToken())),
        switchMapTo(from(this.db.authState.pipe(
          take(1),
          switchMap((user)=>{
            if (user)
              return from(user.getIdToken());
            else
              return of(null);
          })
        ))),
        switchMap(token => this.http.post(environment.apiUrl + '/api/login', { token: token })),
        tap((response: any) => {
          if (response.valid === 'true') {
    
            console.log("effects success");
    
            // localStorage.setItem('token', JSON.stringify(token));
            this.router.navigate(['dash']);
          }
        }),
        map(response => new UserActions.LoginSuccessAction({ response }))//,
        // catchError(error => new UserActions.LoginFailureAction({ error }))
      );
    

    After doing some serious research, I coded the correct answer. Thanks to Chris for his contribution.