user9847788
user9847788

Reputation: 2445

How to resolve Observable mismatch in Angular app?

In my Angular app, I'm getting this error when I try to compile:

Type 'Observable<Promise<void>>' is not assignable to type 'Observable<AuthResponseData>'. Type 'Promise' is missing the following properties from type 'AuthResponseData': kind, idToken, email, refreshToken, and 2 more

Here is the AuthResponseData interface:

export interface AuthResponseData {
  kind: string;
  idToken: string;
  email: string;
  refreshToken: string;
  localId: string;
  expiresIn: string;
  registered?: boolean;
}

Here is the login() method:

login() {

    let authObs: Observable<AuthResponseData>;

    authObs = this.authService.login(this.email, this.password);

    authObs.subscribe(
        resData => {
            console.log('Response Data:', resData);
            this.router.navigateByUrl('/home');
        },
        errRes => {
            console.log('Error Response:', errRes);
        });
}

And here is AuthService.login():

login(email: string, password: string) {
    return of(firebase.auth().signInWithEmailAndPassword(email, password)
      .then((user) => {
        console.log('Service User Value', user);
      }).catch((err) => {
        console.log('Service Error', err);
      }));
  }

Can someone please tell me what changes I need to make so that I'm assigning the correct type in the Observable?

Upvotes: 0

Views: 301

Answers (3)

Barremian
Barremian

Reputation: 31125

This is one of the reasons why I don't prefer mixing promises and observables although it isn't a hack or a workaround.

If you still wish to convert the promise to an observable you could do it using RxJS from (RxJS v6.0.0+). From the docs:

Creates an Observable from an Array, an array-like object, a Promise, an iterable object, or an Observable-like object.

If a then or a catch method if provided to the promise, then the from operator will return an observable of the promise returned by the corresponding method instead of the source promise. It'd be better to remove them when converting.

Try the following

Service

import { from } from 'rxjs';

login(email: string, password: string) {
  return from(firebase.auth().signInWithEmailAndPassword(email, password));
}

Component

login() {
  let authObs: Observable<any>;  // <-- use 'any' instead of a specific type
  authObs = this.authService.login(this.email, this.password);
  authObs.subscribe(
    resData => {
      console.log('Response Data:', resData);
      this.router.navigateByUrl('/home');
    },
    errRes => {
      console.log('Error Response:', errRes);
    }
  );
}

Pre RxJS v6.0.0, please refer here.

Upvotes: 1

Cezary Maszczyk
Cezary Maszczyk

Reputation: 26

It seems that your login method returns Promise not Observable, Promise has no subscribe method. To convert it to Observable you can use from operator. See that question for details: Convert Promise to Observable

EDIT:

First replace of with from to get Observable of response and not Observable of Promise. Then remove catch. It should look something like this:


 // in Component
 authObs = this.loginService('', '');

 authObs.subscribe(
      resData => {
        console.log('Response Data:', resData);

      },
      errRes => {
        console.log('Error Response:', errRes);
      });
  }

  // In service

  public login(email: string, password: string) {
    return from(firebase.auth().signInWithEmailAndPassword(email, password));

  }

Upvotes: 0

user10615718
user10615718

Reputation:

This might solve your problem: Convert Promise to Observable

return firebase.auth().signInWithEmailAndPassword(email, password)
      .then((user) => {
        console.log('Service User Value', user);
      }).catch((err) => {
        console.log('Service Error', err);
      });

This code returns a promise. You're trying to assign your local Observable to the returned Promise. You first need to convert the promise to an observable with Observable.fromPromise.

Upvotes: 0

Related Questions