Angular 我可以完成一个角度FireStore Observable并确保它加载了所有文档吗?

Angular 我可以完成一个角度FireStore Observable并确保它加载了所有文档吗?,angular,firebase,google-cloud-firestore,Angular,Firebase,Google Cloud Firestore,正如标题所说,我想知道我是否可以用FireStore中的数据完成一个Observable,并确保它加载了所有数据 我有一个数据库,每周最多更新一次。我不需要实时更新我的网站 在使用FireStore之前,我可以调用subscribe函数的complete部分中的函数,但由于FireStore Observable从未完成,因此不再工作 我在网上发现,我可以通过取消订阅来“完成”可观察到的数据,但我可以确定它已加载所有数据吗 如果相关的话,这里是我的服务和一些调用该服务的代码。可能还剩下一些其他功

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

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

在使用FireStore之前,我可以调用
subscribe
函数的
complete
部分中的函数,但由于FireStore 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();
        }
    )

requestTracks
方法中,您可以从
tracksCollection.get()
中获得一个可观察对象,将其转换为承诺,并使用结果创建一个新的可观察对象。这没有多大意义

您可能希望执行以下操作:

return tracksCollection.get().pipe(
   map(querySnapshot => querySnapshot.map((doc => doc.data()))
)
然后在组件的
ngondestory
生命周期挂钩中,您可以:

this.trackSubscription.unsubscribe()

我从教程中复制了这个方法。我尝试了你的建议,但得到的错误是'QuerySnapshot'类型上不存在'map'。我可以这样写:
trackscolection.get().pipe(map(querySnapshot=>querySnapshot.docs.map(doc=>doc.data()as Track))
但是“map”中的代码没有执行。(我对角度测量还比较陌生,但仍然感觉不到自己掌握了观察的窍门)另外,我已经退订了Ngondestory,但这还不够早。我想在数据加载后尽快完成可观测数据,以便在加载数据时对数据应用过滤器。(我在屏幕上显示了部分数据)@WhiteFalcon此代码应该可以工作(在您的评论中使用map进行更改)。此外,无需取消订阅,因为
get()
在请求后完成(与例如
valueChanges()
相反)。