1

I'm currently building a project using firebase with the firestore database and Angular. Inside my firestore database i have a collection of tasks and a collection of owners. Each task has a reference (foreign key) to an owner like owner: -l3sdfkl3sdflksdf. An owner can be linked to multiple tasks, where a task can have only one owner.

In one of my Angular components i like to show a list of all my tasks, including some owner information per task. I wrote a service method to subscribe to the collection of tasks and inside that subscription i wan't to subscribe to the owner, per task. Because my component also wants to be triggered when one of the owner properties (for an owner linked to one of the tasks) changes.

I currently thinking about something like this, however i wonder if this is smart, maintainable, how i should unsubscribe etc etc etc:

getTasks(): Observable<Task[]> {
    return this.afs.collection<Task>('tasks').snapshotchanges().map((actions: DocumentChangeAction[]) => {
        let tasks: Task[] = [];
        actions.forEach((action: DocumentChangeAction) => {
            let task: any = { id: action.payload.doc.id, ...action.payload.doc.data() };

            // Per task, subscribe to the owner, how?
            this.getOwner(task.id).subscribe((owner: Owner) => {
                task.owner = owner;
                return tasks;
            });


            tasks.push(task);
        });
        return tasks;
    });
}

I don't like to do the retrieval of each owner in the component itself, it could be that in the future i have multiple components that need this list of tasks including the owner and i simply think it's not the responsibility of the component.

Any tips on how to solve stuff like this? Thanks!

2 Answers2

0

First of all you can put your getOwner and task data handling method in a seperate task.service Service. Component just need to handle UI logic, and in regards to your stream you can optimise it like below (assume you are using rxjs5)

getTasks(): Observable < Task[] > {
return this.afs.collection < Task > ('tasks').snapshotchanges()
  .mergeMap((actions: DocumentChangeAction[]) => Observable.from(actions))
  .switchMap((action: DocumentChangeAction) => {
    let task: any = {
      id: action.payload.doc.id,
      ...action.payload.doc.data()
    };
    // Per task, subscribe to the owner, how?
    return this.taskService.getOwner(task.id).map((owner: Owner) => {
      task.owner = owner;
      return task
    });
  }).reduce((acc,curr)=>{
  acc.push(curr)
  return acc
  },[])
}
Fan Cheung
  • 10,745
  • 3
  • 17
  • 39
  • Hi, thanks for your answer. I'm currently testing it but i get stuc at the reduce part. If i remove the reduce part at the end my subscription on "getTasks" is called A LOT of times, if i add the reduce part it is never called... – Bas Van Den Heuvel Aug 15 '18 at 13:18
  • Try to console.log inside reduce see if it prints anything – Fan Cheung Aug 15 '18 at 13:44
-1

Maybe you should be looking at the switchMap or other map operators of RxJS; flatMap, mergeMap, switchMap and concatMap in rxjs?

Another clear example is given here; https://www.youtube.com/watch?v=6lKoLwGlglE

Lars Meijdam
  • 1,177
  • 1
  • 10
  • 18