1
votes

I have a Firestore document that has two properties and they are all arrays of Ids of different <Game>{} objects elsewhere in the Firestore database.

Is there any way for me to create an observable that would stream an object that contains two separate arrays of the items those ids represent?

I don’t think there is a way to just have one singular stream of objects because (once I subscribe) I wouldn’t know which item belonged to which array as the array sizes are not constant.

I'm new to observables and rxjs and am constantly reading about different operators but I'm kind of stuck here and contemplating of restructuring my data if I can't find a solution.

Right now, I have something like this in my service class but it does not work as I expect it would when I subscribe to the function.

  getPlayerGames(uid: string) {
    return this._db.doc<PlayerGameSession>(`users/${uid}/mygamesession/games`).valueChanges().pipe(
      map(gameObj => {
        let combined1;
        let combined2;

        if (gameObj.prop1) {
          const prop1Streams = gameObj.prop1.map(
            gameId => this._db.doc<Game>(`games/${gameId}`).valueChanges()
          );

          combined1 = combineLatest(...prop1Streams);
        }

        if (gameObj.prop2) {
          const prop2Streams = gameObj.prop2.map(
            gameId => this._db.doc<Game>(`games/${gameId}`).valueChanges()
          );

          combined2 = combineLatest(...prop2Streams);
        }

        return combineLatest(combined1, combined2);

      }),
      switchMap(([c1, c2]) => of({ c1: c1, c2: c2 }))
    );
  }
1

1 Answers

0
votes

You are returnning an observable of an object with two properties from the type of observable, if you are want to return an observable of an object with two arrays with the data you need to combine the array observables, like the example below:

const v1 = new BehaviorSubject('1')
const v2 = new BehaviorSubject('2')
const v3 = new BehaviorSubject('3')
const v4 = new BehaviorSubject('4')

const combined1 = combineLatest(v1, v2)
const combined2 = combineLatest(v3, v4)

const combined3 = combineLatest(combined1, combined2)

combined3
  .pipe(switchMap(([c1, c2]) => of({c1: c1, c2: c2})))
  .subscribe(console.log)

In this example i took four observable combined them into two arrays and then combined those arraies into a combined object of both of them

Try this code:

getPlayerGames(uid: string) {
    return this._db.doc<PlayerGameSession>(`users/${uid}/mygamesession/games`).valueChanges().pipe(
  switchMap(gameObj => {
    let combined1 = of([]);
    let combined2 = of([]);;

    if (gameObj.prop1) {
      const prop1Streams = gameObj.prop1.map(
        gameId => this._db.doc<Game>(`games/${gameId}`).valueChanges()
      );

      combined1 = combineLatest(...prop1Streams);
    }

    if (gameObj.prop2) {
      const prop2Streams = gameObj.prop2.map(
        gameId => this._db.doc<Game>(`games/${gameId}`).valueChanges()
      );

      combined2 = combineLatest(...prop2Streams);
    }

    return combineLatest(combined1, combined2)
       .pipe(switchMap(([c1, c2]) => of({c1: c1, c2: c2}))

  })
);

}