首页 > 解决方案 > 我可以完成一个 Angular FireStore Observable 并确保它加载了所有文档吗?

问题描述

正如标题所说,我想知道我是否可以使用 FireStore 中的数据完成一个 Observable 并确保它加载了所有数据。

我有一个最多每周更新一次的数据库。我不需要实时更新我的​​网站。

在我使用 FireStore 之前,我可以在函数complete部分调用一个函数,subscribe但由于 FireStore Observable 永远不会完成,这不再有效。

我在网上发现我可以通过取消订阅来“完成” Observable,但我可以确定它已经加载了所有数据吗?

如果相关,这里是我的服务和一些调用该服务的代码。可能还有一些来自其他功能的代码。

服务

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { shareReplay, map } from 'rxjs/operators';
import { Track } from '../model/track';

import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore'

const CACHE_SIZE = 1;

@Injectable({
  providedIn: 'root'
})

export class TrackService {

  constructor(private http: HttpClient, private afs: AngularFirestore) { }
  private tracks:Observable<Track[]>;

  getTracks(){
     if (!this.tracks) {
      this.tracks = this.requestTracks().pipe(
        shareReplay(CACHE_SIZE)
      );
    }

    return this.tracks;
  }

  private requestTracks() {
    var tracksStorage: Track[] = [];
    var tracksObservable: Observable<Track[]>;
    var tracksCollection: AngularFirestoreCollection<Track>;
    tracksCollection = this.afs.collection("Songs");
    tracksCollection.get().toPromise().then(function(querySnapshot) {
      querySnapshot.forEach(function(doc) {
        tracksStorage.push(doc.data() as Track);
      })
    });

    tracksObservable = new Observable(observer => {
      observer.next(tracksStorage);
    })
    return tracksObservable;
  }
}

调用服务的代码

this.trackSubscription = this.trackService.getTracks() 
    .subscribe(
        trackData => 
        {
            trackData.forEach(track => {
                console.log("Track data:"); // this is also not called. But probably different problem.
                console.log(track);
                track.lyrics = track.lyrics.replace(/(\\n)/g, '\n');
            });
            this.tracks = trackData as Track[]
        },
        err => {
            console.log("error in Track Component");
            console.log(err);
        },
        () => {
            console.log('Retrieving tracks completed'); // never called
            this.loadWithParams();
        }
    )

标签: angularfirebasegoogle-cloud-firestore

解决方案


在该requestTracks方法中,您有一个 Observable tracksCollection.get(),您将其转换为 Promise,并使用结果创建一个新的 Observable。这没有多大意义。

您可能想要执行以下操作:

return tracksCollection.get().pipe(
   map(querySnapshot => querySnapshot.map((doc => doc.data()))
)

然后在ngOnDestroy组件的生命周期挂钩中,您可以:

this.trackSubscription.unsubscribe()

推荐阅读