【问题标题】:How do I retrieve a storage downloadURL from inside a firestore collection using RxJS?如何使用 RxJS 从 Firestore 集合中检索存储下载 URL?
【发布时间】:2021-11-17 08:56:09
【问题描述】:

我正在使用 Angular 12 和 AngularFire / Firebase 9(模块化)。我正在努力使用 RxJS 从存储中检索 downloadURL 并将其添加到集合结果的每个项目中。使用以下代码,我可以在控制台中查看“ZoneAwarePromise”下的数据,但无法通过模板查看数据。

const listCollection = collectionData(collection(this.firestore, 'lists'), {idField: 'id'});
this.lists = listCollection.pipe(take(1), map(lists => lists.map(async list => {
  const imgRef = ref(this.storage, list.metaImage);
  const coverImg = await getDownloadURL(imgRef);
  return {...list, coverImg}
})));

【问题讨论】:

    标签: javascript google-cloud-firestore rxjs firebase-storage


    【解决方案1】:

    使用 switchMap 组合结果确实有效;但是它会在 Angular 中导致一些渲染阻塞问题(即,在模板显示结果之前等待所有“列表”项返回 getDownloadUrl())。从原始代码中删除“async”和“await”,并在 Angular 模板中添加“async”管道,可以让数据在没有渲染阻塞的情况下流动。

    list.component.ts

    const listCollection = collectionData(collection(this.firestore, 'lists'), {idField: 'id'});
    this.lists = listCollection.pipe(take(1), map(lists => lists.map(list => {
      const imgRef = ref(this.storage, list.metaImage);
      const coverImg = getDownloadURL(imgRef);
      return {...list, coverImg}
    })));
    

    list.component.html

    <div class="card" *ngFor="let list of lists | async">
      <div class="card-image">
        <img [src]="list.coverImg | async" />
      </div>
      <h2 class="card-title-lower">
        <a [routerLink]="['/list', list.id]">{{ list.title }}</a>
      </h2>
    </div>
    

    【讨论】:

      【解决方案2】:

      很难从您在这里写的内容中确定,但看起来this.lists 是一个发出承诺列表的可观察对象。这就是 async 关键字的作用,它是创建 Promise 的语法糖。

      您没有在任何地方获取/使用承诺中的(即:您没有在任何地方awaiting 他们)。

      一种解决方案是重写你的 Promise,因为 observable 使用 forkJoin 来运行你的 observable 数组。

      可能看起来像这样:

      const listCollection = collectionData(collection(this.firestore, 'lists'), {idField: 'id'});
      
      this.lists = listCollection.pipe(
        take(1), 
        map(lists => lists.map(list => {
          const imgRef = ref(this.storage, list.metaImage);
          return from(getDownloadURL(imgRef)).pipe(
            map(coverImg => ({...list, coverImg}))
          )
        })),
        switchMap(listsCalls => forkJoin(listsCalls))
      );
      

      【讨论】:

      • 谢谢!我为模糊的代码道歉。 "getDownloadURL" 实际上是一个 Promise,但是用 RxJS 的 "from" 函数包装它可以使代码按预期工作。
      • 很高兴它有帮助。用from 更新了我的答案
      猜你喜欢
      • 2022-01-23
      • 2021-10-01
      • 1970-01-01
      • 2021-07-13
      • 2019-04-11
      • 2019-02-05
      • 1970-01-01
      • 2020-07-10
      • 2020-09-01
      相关资源
      最近更新 更多