Angular 2 Firebase Observable 承诺不会返回任何东西

Posted

技术标签:

【中文标题】Angular 2 Firebase Observable 承诺不会返回任何东西【英文标题】:Angular 2 Firebase Observable to promise doesn't return anything 【发布时间】: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? 是的,对不起!我在复制代码时切换了它们。 【参考方案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) 不会。见***.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;

快乐编码

【讨论】:

以上是关于Angular 2 Firebase Observable 承诺不会返回任何东西的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2 - Firebase 在页面刷新时保持登录状态

Angular 2 Firebase Observable 承诺不会返回任何东西

找不到在 Angular 中导入 Firebase 身份验证

为啥我在尝试从 Angular 2 应用程序连接和查询 Firebase 数据库时收到此错误消息?

重新路由到带有/用户数据 Angular 2 和 Firebase 的个人资料页面

使用 AngularFire2 (Angular2 rc.5) 访问 firebase.storage()