【问题标题】:Angular 2 Firebase Observable to promise doesn't return anythingAngular 2 Firebase Observable 承诺不会返回任何东西
【发布时间】:2017-06-12 14:50:25
【问题描述】:

我目前正在使用 AngularFire2 开发 Angular 2 项目,并且正在尝试将 FirebaseListObservable 转换为 Promise。我知道这没有多大意义,因为 Observables 更有用,但这个函数将成为另一个函数的一部分,其中多个 Promise 被链接。而且我不熟悉如何在一系列承诺中订阅 Observables ......该函数在服务中执行,但它似乎没有返回任何内容。 基本上,我想要做的是检查 Firebase 列表是否已经存在具有特定名称的对象并返回 true 或 false。

服务

constructor(private _af: AngularFire) { }

nameExists(name: string): Promise<boolean> {

 return this._af.database.list('users')
  .map(users => {

    let exists = false;
    users.forEach(user => {
      if(user.name.toLowerCase() === name.toLowerCase()) {
        console.log('Name already exists!');
        exists = true;
      }
    });
    return exists;
  }).toPromise();
}

组件

constructor(private _usersService: UsersService) { }

check(name) {
 this._usersService.nameExists(name)
  .then(bool => console.log(bool));
}

因此,当有匹配项时,该函数将被执行并且在打印到控制台时似乎可以正常工作。但是,组件中的 console.log() 不会被执行。我想“那么”部分永远不会到达。另外,有没有办法在找到匹配项后停止 forEach 循环?

任何帮助将不胜感激,因为我根本找不到任何答案。

【问题讨论】:

  • 在你的组件中是 _dibbService 假设是 _usersService?
  • 是的,对不起!我在复制代码时切换了它们。

标签: typescript angularfire2 angular2-observables


【解决方案1】:

问题在于toPromise 运算符将可观察对象转换为可解析为可观察对象最终值的承诺。这意味着 observable 必须在 promise 解决之前完成。

在 AngularFire2 中,list 和 object observables 不完整;每当数据库更改时,它们都会重新发出。

你可以使用first操作符来解决这个问题,它获取第一个发出的值,然后完成组合的observable:

import 'rxjs/add/operator/first';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
...
return this._af.database
  .list('users')
  .map(users => {

    let exists = false;
    users.forEach(user => {
      if (user.name.toLowerCase() === name.toLowerCase()) {
        console.log('Name already exists!');
        exists = true;
      }
    });
    return exists;
  })
  .first()
  .toPromise();

【讨论】:

  • 就在你认为你已经使用 Observables 足以理解它们的时候......非常感谢!成功了!
  • 使用.first()时,订阅是否丢失?
  • @Luis 否,first 是“普通”运算符,仍然需要调用 subscribe。但是,toPromise 不是。它涉及对subscribe 的隐式调用,因为它将可观察对象转换为承诺。当 observable 完成时,返回的 Promise 解决。此外,当一个 observable 完成时,所有订阅者都会自动取消订阅。
  • 为什么首先而不是take(1)
  • @Jimmy 如果源在没有发出值的情况下完成,first 将出错 - take(1) 不会。见stackoverflow.com/a/42346203/6680611。除非我希望源代码有时会在不发射的情况下完成,否则我倾向于使用 first
【解决方案2】:

我通过在收到第一个数据后以惰性方式取消订阅来解决这个问题:)

const userSubs$ = this.db.object(`branch/${branchId}/products`).subscribe(
                     async (payload: any) => {
                      userSubs$.unsubscribe();
                       })

或者将你的代码转换成这样的好方法:)

 const eventref = this.db.database.ref(`branch/${branchId}/products`);
  const snapshot = await eventref.once('value');
  const productArray = snapshot.toJSON()
  return productArray;

快乐编码

【讨论】:

    猜你喜欢
    • 2016-10-25
    • 1970-01-01
    • 1970-01-01
    • 2017-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-21
    相关资源
    最近更新 更多