Search code examples
angulartypescriptrxjsangularfire2

Is this the correct way to use rxjs MergeMap in angularfire2?


I'm new in angular and rxjs, I'm trying to get three different values from firebase using angularfire2 and rxjs, and return it as a promise. After several research and trying i finally made it by using this code.

Here's the code (assuming afdb is angularfire-database):

getThreeValues() {
    return this.afdb.list('firebaseref1').valueChanges().pipe(
        map(data => {
            return data.length;
        }),

        mergeMap(first => {
            return this.afdb.object('firebaseref2').valueChanges().pipe(
                map(second => {
                    return ({first: first, second: second})
                }),
                take(1)
            );
        }),

        mergeMap(firstsecond => {
            return this.afdb.list('firebaseref3').valueChanges().pipe(
                map(third => {
                    return ({...firstsecond, third: third})
                }),
                take(1)
            );
        }),

        take(1))
        .toPromise();
}

The code works and I get promise which resolve into object that contain the three values I need.

The problem is that I'm not sure if this is the best way (as I'm not sure how this code works).


Solution

  • Since you are pretty sure you will only take the first value of your .valueChanges(), it will be much more efficient to wrap them into a .forkJoin() instead of .mergeMapping them all the way. With the help of destructuring from javascript, your code can look much simpler like this:

    getThreeValues() {
        return forkJoin(
            this.afdb.list('firebaseref1').valueChanges().pipe(take(1)),
            this.afdb.object('firebaseref2').valueChanges().pipe(take(1)),
            this.afdb.object('firebaseref3').valueChanges().pipe(take(1))
        )
            .pipe(
                map(([first, second, third]) => ({
                    first: first.length,
                    second,
                    third
                }))
            ).toPromise()
    }