【问题标题】:How to resolve Observable mismatch in Angular app?如何解决 Angular 应用程序中的 Observable 不匹配问题?
【发布时间】:2020-05-04 13:20:39
【问题描述】:

在我的 Angular 应用程序中,当我尝试编译时出现此错误:

类型 'Observable<Promise<void>>' 不可分配给类型 'Observable<AuthResponseData>'。类型“承诺”缺少 来自“AuthResponseData”类型的以下属性:种类、idToken、 电子邮件、refreshToken 和另外 2 个

这里是AuthResponseData接口:

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

这里是 login() 方法:

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);
        });
}

这里是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);
      }));
  }

谁能告诉我我需要做哪些更改才能在 Observable 中分配正确的类型?

【问题讨论】:

  • 这里的第一个答案是指向正确的方向。您正在返回一个 void 类型的承诺的可观察对象,这意味着这一行 --> return of(firebase.auth().signInWithEmailAndPassword(email, password) 不要做所有的事情并捕获错误内容并将您的承诺 firebase.auth().signInWithEmailAndPassword(email, password) 转换为使用 from 而不是“of”关键字的可观察对象。然后正确订阅。我强烈推荐使用像 catchError 这样的管道操作符。

标签: angular typescript google-cloud-firestore


【解决方案1】:

这就是为什么我不喜欢混合 Promise 和 observables 的原因之一,尽管它不是一种 hack 或解决方法。

如果你仍然希望将 promise 转换为 observable,你可以使用 RxJS from (RxJS v6.0.0+) 来实现。来自文档:

从一个数组创建一个 Observable,一个类似数组的对象,一个 Promise, 一个可迭代的对象,或者一个类似 Observable 的对象。

如果将thencatch 方法提供给promise,则from 运算符将返回相应方法返回的promise 的可观察对象,而不是源promise。转换时最好去掉。

试试下面的

服务

import { from } from 'rxjs';

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

组件

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,请参考here

【讨论】:

  • 你确定使用 then 并像这样通过 from(promise.catch.error) 捕获和环绕它吗?我认为不需要 catch 和 then 子句,是吗?问候
  • 感谢您的回答,但我已经尝试过此代码并且正在发生相同的行为。我仍在使用无效凭据导航
  • @sagat:你说得对,如果我们提供thencatch 方法,它会返回它们返回的promise。
  • @user9847788 请从 Promise 中删除 thencatch 方法。我已经更新了代码。
【解决方案2】:

这可能会解决您的问题: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);
      });

此代码返回一个承诺。您正在尝试将本地 Observable 分配给返回的 Promise。您首先需要使用 Observable.fromPromise 将 promise 转换为 observable。

【讨论】:

  • 感谢您的回答。我现在用不同的代码更新了我的问题,并解释了这个问题。你能看一下吗?
【解决方案3】:

看来您的login 方法返回Promise not Observable,Promise 没有subscribe 方法。要将其转换为 Observable,您可以使用 from 运算符。有关详细信息,请参阅该问题:Convert Promise to Observable

编辑:

首先将 of 替换为 from 以获得响应的 Observable 而不是 Promise 的 Observable。然后取下捕捉。它应该看起来像这样:


 // 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));

  }

【讨论】:

  • 感谢您的回答。我现在用不同的代码更新了我的问题,并解释了这个问题。你能看一下吗?
猜你喜欢
  • 1970-01-01
  • 2020-06-27
  • 1970-01-01
  • 2019-01-06
  • 2016-03-20
  • 1970-01-01
  • 2020-02-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多