Search code examples
angulartypescriptobservableangularfire

Returning an observable from inside a subscription?


I'm trying to find a certain document in Angularfire, the Firebase library for Angular. I've got an observable which returns the correct document ID, and I'm subscribing to this observable and using the ID inside to fetch all of the data on the document, which also comes back as an observable.

  getSessions(date: firestore.Timestamp) {
    this.db.collection('days', ref => ref.where('date', '==', date)).snapshotChanges().subscribe(docRef => {
      return this.db.collection('days').doc(docRef[0].payload.doc.id).collection('sessions').valueChanges();
    })
  }

My current attempt at this, firstly, gets the ID of the document I want. This comes in the first observable that I subscribe to. Inside this subscription, I use the ID to get the nested sessions collection. this.db.collection('days').doc(docRef[0].payload.doc.id).collection('sessions').valueChanges(); gets me exactly what I need, but if I try to return this, the receiving method will only get an undefined value. This strikes me as an asynchronous issue.

I've seen some posts that suggested using switchMap, but my attempts to do this haven't worked either.

  getSessions(date: firestore.Timestamp) {
    this.db.collection('days', ref => ref.where('date', '==', date)).snapshotChanges().pipe(switchMap(docRef => {
      return this.db.collection('days').doc(docRef[0].payload.doc.id).collection('sessions').valueChanges();
    }))
  }

For reference, the collection method always returns an observable. If I ran the innermost line by itself, outside of any subscriptions, it would return an observable and complete my required behaviour just fine.


Solution

  • I think switchMap should work fine, you have to return the observable in the function though.

    getSessions(date: firestore.Timestamp) {
        // !! check out the first return here !!
        return this.db.collection('days', ref => ref.where('date', '==', date)).snapshotChanges().pipe(switchMap(docRef => {
          return this.db.collection('days').doc(docRef[0].payload.doc.id).collection('sessions').valueChanges();
        }))
      }
    
    ...
    this.getSessions(...).subscribe(data => { console.log(data) });