Search code examples
firebasefirebase-realtime-databaserxjs

RxJs Compose a list of Observables and then combine (Firebase)


I'm attempting to combine a list of observables, but haven't had luck with zip or other maps.

What I want to do is get a list of Genres for a given Artist Id. I'm using firebase, so it's a nosql database. I have a 'genresPerArtist' list that is a list of Artist keys, and each Artist key has a list of Genre keys. Structure:

    { 
         genresPerArtist: {
             artist1: {
                 genre1: true,
                 genre2: true,
                 genre3: true
            }
        },
         genres: {
             genre1: {
                name: 'Alternative'
             },
             genre2: {
                name: 'Jazz'
             } 
        }
    }

Here's the start of the function that I have:

getGenresByArtistId(artistId: string): Observable<any> {
     return this.db.list(`/genresPerArtist/${artistId}`)
         .flatMap((genres: IDictionary[]) => {
             return genres.map(genre => this.db.list(`/genres/${genre.$key}`));
             // return Observable.zip(obvs);
         });

I'm not really sure what do do with the list that I get back from genresPerArtist. What I want to do, is take each genre.key (genre1, genre2, genre3), and use each one to fetch the value from 'genres'. I thought I could return a .zip, and then map over that, but I was not getting a response from zip.


Solution

  • @cartant, thanks, that included what I needed, forkJoin.

    // Compose an observable based on the genresPerArtist:
            return this.db.list(`/genresPerArtist/${artistId}`)
            // Each time the genresPerArtist emits, switch to unsubscribe/ignore any pending user queries:
            .switchMap(genres => {
                // Map the genres to the array of observables that are to be joined.
                let genreObservables = genres.map(genre => this.db.object(`/genres/${genre.$key}`).first());
                return Observable.forkJoin(...genreObservables);
            });