简体   繁体   English

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

[英]AngularFire / Firestore - Return collections and documents as a service

I have several pages that reference the same node in firestore, each pulling different segments from the firestore node. 我有几个页面引用了Firestore中的同一节点,每个页面都从Firestore节点中提取了不同的段。 For example, a summary page might pull through album title, date, genre and image, whilst another page might pull through just the title, artist and record label. 例如,摘要页面可以浏览专辑标题,日期,流派和图像,而另一页面可以仅浏览标题,艺术家和唱片公司。 A couple of questions: 几个问题:

  1. Is it possible to turn one of the firestore queries into a service? 是否可以将其中一个Firestore查询转换为服务?
  2. If so, does that mean the data is only read once whilst navigating across different pages (angular components) that use the same service? 如果是这样,这是否意味着在使用相同服务的不同页面(角度组件)之间导航时只能读取一次数据?
  3. Will the query only run again when data is modified in firestore through the observable? 仅通过可观察对象在Firestore中修改数据时,查询才会再次运行吗? (" return Observable.create(observer => { " ) (“ return Observable.create(observer => { ”)

I have tried a service with the code below. 我已经尝试使用下面的代码进行服务。 However, the issue observed is that on page refresh, the data isn't present. 但是,观察到的问题是页面刷新时不存在数据。 It is however present whilst navigating through the site. 但是,它在浏览站点时存在。 I believe this is because my page is running before the observable is returned. 我相信这是因为我的页面在返回observable之前正在运行。 Is there a way to wrap up the query as an observable? 有没有办法将查询包装为可观察的?

Any assistance would be greatly appreciated. 任何帮助将不胜感激。

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

When I build my observables, I try to use operators as much as I can until I get the data I want to display in my UI. 建立可观察值时,我会尽量使用运算符,直到获得要显示在UI中的数据为止。

You don't want to implement too much code in the subscribe method because you break the reactive paradigm by doing so. 您不想在subscribe方法中实现太多代码,因为这样做会破坏反应式范例。 Instead, extract you data in your observable and display it in your template. 取而代之的是,将数据提取到您的可观察对象中并显示在模板中。 Don't forget to use the async pipe in your template to display your data when it gets fetched by your application. 当应用程序获取数据时,请不要忘记在模板中使用异步管道来显示数据。

I would do something like this: 我会做这样的事情:

// 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$;
  }

By doing so, when your data is updated in firestore, it will be fetched automatically by your application since you use an observable. 这样一来,当您在Firestore中更新数据时,由于您使用的是可观察对象,因此应用程序会自动提取这些数据。

In your component, in the onInit() method after getting your album id from the url: this.album_cover$ = this.albumService.getAlbumCover(albumId); 在您的组件中,从网址获取专辑ID后,在onInit()方法中: this.album_cover$ = this.albumService.getAlbumCover(albumId);

Finally, in my template, I would do : 最后,在模板中,我将执行以下操作:

<div>{{album_cover$ | async}}</div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM