我有几个引用firestore中相同节点的页面,每个页面都从firestore节点中拉出不同的段。例如,摘要页面可能会浏览专辑标题,日期,流派和图像,而另一个页面可能只会浏览标题,艺术家和唱片标签。几个问题:
我尝试过使用以下代码的服务。但是,观察到的问题是在页面刷新时,数据不存在。然而,它在浏览网站时存在。我相信这是因为在返回observable之前我的页面正在运行。有没有办法将查询包装为可观察的?
非常感谢任何协助。
getAlbumData() {
this.albumDoc = this.afs.doc(`albums/${this.albumId}`);
this.album = this.albumDoc.snapshotChanges();
this.album.subscribe((value) => {
// The returned Data
const data = value.payload.data();
// Firebase Reference
var storage = firebase.storage();
// If album cover exists
if (data.project_signature != undefined) {
// Get the Image URL
var image = data.album_cover_image;
// Create an image reference to the storage location
var imagePathReference = storage.ref().child(image);
// Get the download URL and set the local variable to the result (url)
imagePathReference.getDownloadURL().then((url) => {
this.album_cover = url;
});
}
});
}
答案 0 :(得分:2)
当我构建我的observable时,我会尝试尽可能多地使用运算符,直到我获得要在UI中显示的数据。
您不希望在subscribe方法中实现太多代码,因为您通过这样做打破了反应范例。 而是在您的observable中提取数据并将其显示在模板中。 不要忘记在模板中使用异步管道,以便在应用程序获取数据时显示数据。
我会做这样的事情:
// In AlbumService
getAlbumCover(albumId: string) {
const albumDoc = this.afs.doc(`albums/${albumId}`);
const album_cover$ = this.albumDoc.snapshotChanges().pipe(
// get the album data from firestore request
map(data => {
return {
id: data.payload.id,
...data.payload.data()
};
}),
// emits data only if it contains a defined project_signature
filter(album => album.project_signature),
// prepare the imagePath and get the album cover from the promise
mergeMap(album => {
const storage = firebase.storage();
const image = album.album_cover_image;
const imagePathReference = storage.ref().child(image);
return imagePathReference.getDownloadURL();
})
);
return album_cover$;
}
通过这样做,当您在firestore中更新数据时,您的应用程序将自动获取它,因为您使用了一个observable。
在您的组件中,在从网址获取相册ID后的onInit()方法中:
this.album_cover$ = this.albumService.getAlbumCover(albumId);
最后,在我的模板中,我会这样做:
<div>{{album_cover$ | async}}</div>