0
votes

I have an array of Objects, we'll say it's off type Objects[].

I need to map each Object to another type of Object, eg, DestinationObject[] however there is a property on DestinationObject[] that I need to look in Firebase for so I'll need to do a subscribe, or a pipe(map()).

Unfortunately if I do a Subscribe, I get returned a Subscription, and if I do a pipe(map()) I get an list of Observables, rather an Observable List of Objects (ie I want Observable<Object[]> and not Observable<Object>[]

Here's the code:

  processUsers(users: Users[], groupUsers: Users[]): Observable<MappedUser[]> {
    return groupUsers.map(groupUser => {
      return this.firebaseService.SubscribableFunction(groupUser.id).pipe(map(array => {
        return {
          name: groupUser.name,
          arrayLength: array.length,
        } as MappedUser;
      }));
    });
  }

So two simple array objects, we do get a MappedUser returned, but because of the pipe(map()) on the SubscribableFunction, that returns an Observable and therefore the map on the first line returns a list of Observable. Which wasn't quite what I wanted.

Do you have any solutions? I've tried map, mergeMap, from() of() but it doesn't seem to work as expected.

Update Here's the subscribable function as requested:

  SubscribableFunction(userId: string): Observable<Equipment[]> {
    const collection = this.afs.collection<Equipment>('equipment', ref => ref.where('userId', '==', userId));
    return collection.snapshotChanges().pipe(map(items => {
      return items.map(item => {
        return {
          id: item.payload.doc.id,
          ...item.payload.doc.data(),
        } as Equipment;
      });
    }));
  }
1

1 Answers

0
votes

You're almost there. Once you've mapped the source array to an array of observables, you'd end with something like [obs1, obs2, obs3, ...]. So here you could use RxJS forkJoin function to trigger all the observables in parallel and get the results as an array of objects.

Try the following

processUsers(users: Users[], groupUsers: Users[]): Observable<MappedUser[]> {
  return forkJoin(groupUsers.map(groupUser => { // <-- return `forkJoin` here
    return this.firebaseService.SubscribableFunction(groupUser.id).pipe(map(array => {
      return {
        name: groupUser.name,
        arrayLength: array.length,
      } as MappedUser;
    }));
  }));
}

Now you could subscribe to the function

processUsers(...).subscribe(
  res => console.log(res), // would log `[{MappedUser}, {MappedUser}, {MappedUser},... ],
  err => // good practice to handle HTTP errors
);

Note: RxJS forkJoin will only emit when all the input observables complete. If you wish to have a stream of data from the observables, you could look into zip or combineLatest. You could find the differences between them here.