如何使用RxJS从firestore集合中检索存储下载url ?



我正在使用AngularFire/Firebase 9(模块化)的Angular 12。我正在努力使用RxJS从存储中检索下载url并将其添加到集合结果的每个项目。使用以下代码,我可以在控制台中查看"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}
})));

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

你没有使用从任何地方的承诺(即:你不是在任何地方await他们)。

一个解决方案是将你的承诺重写为可观察对象,使用forkJoin来运行你的可观察对象数组。

可能像这样:

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))
);

使用switchMap来组合结果确实有效;然而,它会导致Angular中的一些渲染阻塞问题(例如等待所有列表)。项返回getDownloadUrl(),模板才能显示结果)。删除"async"one_answers";await"从原始代码中添加了"async"到Angular模板的管道允许数据在没有渲染阻塞的情况下流动。

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>

最新更新