AngularFire / Firestore - 将集合和文档作为服务返回

时间:2018-01-22 11:33:50

标签: javascript angular google-cloud-firestore angular-services angular2-observables

我有几个引用firestore中相同节点的页面,每个页面都从firestore节点中拉出不同的段。例如,摘要页面可能会浏览专辑标题,日期,流派和图像,而另一个页面可能只会浏览标题,艺术家和唱片标签。几个问题:

  1. 是否可以将其中一个firestore查询转换为服务?
  2. 如果是这样,这是否意味着在浏览使用相同服务的不同页面(角度组件)时只读取一次数据?
  3. 当通过observable在firestore中修改数据时,查询是否只会再次运行? (" 返回Observable.create(observer => {")
  4. 我尝试过使用以下代码的服务。但是,观察到的问题是在页面刷新时,数据不存在。然而,它在浏览网站时存在。我相信这是因为在返回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;
          });
        }
      });
    }
    

1 个答案:

答案 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>