【问题标题】:Transform Observable<any> to Observable<any[]>将 Observable<any> 转换为 Observable<any[]>
【发布时间】:2017-07-03 18:44:47
【问题描述】:

我正在使用 firebase 实时数据库开发 ionic3 应用程序。因此我使用angularfire2。该应用程序允许用户存储链接。链接由 url 和相关标签组成。这是我的数据库结构的样子:

所有链接都位于/links/。 对于用户,链接存储为引用键,位于/users/this.user/links/

在视图中,我想列出某个用户的所有链接。 模板详情:

   <ion-item *ngFor="let item of items | async">
      <h3>{{item.url}}</h3>
      <!-- TODO: add tags and other meta information -->
    </ion-item>

这是组件构造函数中发生的事情:

this.items = this.db.list('/users/' + this.user + '/links/')
    .flatMap(x => x)
    .flatMap(x => {
        let y: any = x;
        return this.db.list('/links/' + y.$key);
    })
    .map(res => {
        let url: string;
        let tags: string[] = [];

        for (let r of res) {

                // filter out tags
                if (r.$key === 'tags') {
                    for (let key in r)
                        if (key) tags.push(key);
                }

                // filter out url
                if (r.$key === 'url') {
                    for (let key in r) {
                        url = r[key];
                        break;
                    }
                }
            }
        } // for (let r of res)

        let link: Link = new Link(url, tags);
        return link;
    });

this.items.subscribe(res => {
    console.log(res);
});

这样我的最终 observable 会发出用户链接对象。组件订阅中的console.log(res) 显示了想要的结果:

但由于我发出 Link 对象,Angular 告诉我 ngFor 只支持可迭代对象:

最后,我的问题是:

  1. 如何将 items 可观察对象转换为模板中 ngFor 可迭代的对象?

  2. 有没有更好的方法来使用 rxjs 运算符进行我想要的过滤?

提前非常感谢!

【问题讨论】:

  • 在完成发射项目后,可观察对象是否完成?
  • 您正在返回一个Link 对象。你想迭代哪个数组?是tags吗?
  • CozyAzure:我想要一个链接列表,每个链接都由它的 url 和它的标签组成。因此,我构建了 Link 对象以在模板中为我的 ngFor 提供。 @ThinkingMedia 我不希望 observable 完成,因为我已连接到实时数据库,如果添加了新链接,我的视图也必须更新。

标签: angular rxjs observable angularfire2 ngfor


【解决方案1】:

这就是你在 Rx 中需要做的事情。我假设您想删除响应中的所有数据,只获取标签和 url

const linkFromRaw = linkList => linkList
    .map(linkResponse => new Link(linkResponse.url, linkResponse.tags);

const linkToDetail = link => this.db.list('/links/' + link.$key))

this.items = this.db.list('/users/' + this.user + '/links/')
  .flatMap( links => Observable.forkJoin(links.map(linkToDetail))
     .reduce(
       (finalResponse, linkResponseArr) =>[...finalResponse, ...linkResponseArr],
       []
     )
  )
  .map(links => links.map(linkFromRaw));

【讨论】:

  • 鉴于/users/this.user/links/ 中的两个链接引用,第一个 flatMap 发出 [Object, Object],其中每个都由 $value: true, $key:'linkReferenceKey' 组成,我猜这是有意的,但是 第二个 flatMap 发出一个空数组[]。因此 map 没有收到任何东西。
  • 忘记了一个语句,你现在可以用更新的代码试试
  • 这个解决方案和我上面的一样,但是更干净。感谢那。 toArray() 是我将 observable 从 Link 转换为 Link[] 所需的全部内容。但实际的问题是toArray() 没有发出任何东西。在 toArray() 之前添加 take(3) 效果很好,但仅适用于 3 个元素的参数。由于我不知道会有多少物品到达,我怎样才能实现toArray() 发射?
  • 我有这个疑问,它是如何工作的。谢谢你,现在我明白它不会起作用了。我将更新答案以使其正常工作。
  • 如果可行,你可以试试。如果它不起作用,我会在 plnkr 中尝试自己并为您提供有效的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-25
  • 2023-04-10
  • 2018-08-14
  • 2018-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多