【问题标题】:Nesting Observables with Angularfire2 (TypeScript)使用 Angularfire2 (TypeScript) 嵌套 Observables
【发布时间】:2017-06-04 12:05:07
【问题描述】:

我有以下非规范化 Firebase 结构:

members
  -memberid1
    -threads
       -threadid1: true,
       -threadid3: true
    -username: "Adam"
    ...

threads
  -threadid1
      -author: memberid3
      -quality: 67
      -participants
         -memberid2: true,
         -memberid3: true
      ...

我在我的组件中列出了由quality 排序的threads

featured-threads.component.ts

constructor(af: AngularFire) {
    this.threads = af.database.list('/threads', {
        query: {
            orderByChild: 'quality',
            endAt: 10
    }
});

以下是我观点的摘录:

featured-threads.component.html

<div *ngFor="let thread of threads | async" class="thread-tile">
...
    {{thread.author}} //Renders memberid3
...
</div>

这里不渲染memberid3,我想获取对应成员的用户名属性值。

herehere 解决方案都在构造函数之外获取它们的 observable,而不是在 Angularfire2 docs 中演示的内部。他们使用this.af.database。当我在构造函数中使用 this 关键字时,TypeScript 会警告它不会将 af 识别为组件属性(因为它显然不是)。我可以通过声明属性af: Angularfire; 在构造函数之外使用this,但随后我收到控制台错误TypeError: Cannot read property 'database' of undefined,我认为这与声明属性与注入AngularFire 服务。我也尝试了其他一些可能太滑稽而与这个问题无关的事情。

我不完全确定这里发生了什么。这个问题使我无法创建一个方法,我可以简单地将author 的值从threads 作为参数传递给该方法。这是因为不能在构造函数内部定义方法,而在构造函数外部af为null。

我什至不完全确定这是否解决了核心问题。我希望能够随时加入/嵌套这些 observables,而不仅仅是在这种更简单的情况下,当我受益于到 memberid 的直接路径时。有许多关于嵌套可观察对象的问题,其解决方案不使用 Angularfire 2。不幸的是,我无法将它们转换为 Angularfire 2 解决方案。

更新

我将组件中的所有逻辑都移到了服务中,现在将服务的方法 getFeaturedThreads() 注入到组件中:

ngOnInit() {
    this.threads = this.featuredThreadsService.getFeaturedThreads()
    this.threads.subscribe( 
        allThreads => 
            allThreads.forEach(thisThread => {
                this.featuredThreadsService.getUsername(thisThread.author)
                    .subscribe( 
                        username => console.log(username))
            })
    )
}

getUserName() 看起来像这样:

getUsername(memberKey: string) {
    return this.af.database.object('/members/' + memberKey + '/username')
}

目前,这会将每个 memberusername 属性记录到控制台。不幸的是,我只拿到了钥匙。值为空:

...这对我来说很奇怪,因为getUsername() 已成功将成员 ID 传递到查询路径中。

这是从我的 Firebase 控制台视图中抓取的,显示路径是正确的。

我认识到这是一个使用问题,而不是技术问题。

【问题讨论】:

  • 如果要在构造函数外访问af字段,在它前面加上private。 private af: AngularFire。现在你可以这样做了。af.someMethod

标签: angular firebase firebase-realtime-database angularfire2


【解决方案1】:

我会这样实现它,我把它移到 ngOnInit 因为你真的不应该在构造函数中这样做。只需在构造函数中的 af 声明之前添加 private。

public ngOnInit() {
    this.threads = this.af.database.list('/threads', {
        query: {
            orderByChild: 'quality',
            endAt: 10
        }
    }).do(threads => {
        threads.forEach(thread => {
            thread.author = this.af.database.getName(thread.author); //actual method to get the username
        });
    });
}

还有你的组件 html

<div *ngFor="let thread of threads | async" class="thread-tile">
...
    {{thread.author | async}}
...
</div>

【讨论】:

  • 我收到打字稿警告,指出do 属性不会在FirebaseListObservable&lt;any[]&gt; 类型上退出。
  • 您必须导入该运算符。 'rxjs/add/operators/do' 我想。
  • 我很想知道您是如何定义该方法的。为了将do 附加到this.threads,我必须将类型从 FirebaseListObservable 更改为 Observable。由于该方法不是database 的方法,我看不出它是如何附加到它的。我实现了this.getUsername(thread.author); 在这些调整之后,我的方法返回一个呈现为[object Object] 的对象。
  • FirebaseListObservable 继承自 Observable,所以 do 应该可用。它可能呈现为对象 Object 因为它有一个带有实际用户名的字段。你必须映射到那个。
  • 感谢您到目前为止的帮助,但没有具体解决问题,这个答案是不完整的。我不确定对象 Object 是否是空的可观察对象(这可能吗?),因为当我将 thread.author 记录到控制台时,对象中没有键或值。我已经阅读了一些关于 RxJS 操作符的文章,但无法弄清楚 .map 的用法来从您正在谈论的字段中获取值——也就是说,如果 observable 甚至被满足的话。跨度>
猜你喜欢
  • 2016-08-31
  • 2017-05-22
  • 2017-07-21
  • 2019-10-27
  • 1970-01-01
  • 2022-01-24
  • 2019-08-04
  • 2017-08-10
  • 2017-03-20
相关资源
最近更新 更多