5

I need to subscribe multiple times in order to get the right data fro my NoSQL database. In order to fetch user list of specific project, I do this:

ngOnInit() {
    //Subscription 1 (Service): Get project data
    this.projectService.getCurrentproject().take(1).subscribe(projectData => {
        console.log('Got project data.');
        //Subscription 2: Get project user IDS
        this.af.database.list('/project_roles/'+projectData.$key)
            .subscribe((userMeta) => {
                });
            });
}
  • As you can see, a subscription, inside a subscription, inside a subscription.. And each subscription depends on the previous one reslt.

  • Subscription 3 and 4 can be parallel.

The code works well, but am I missing something or this is how I suppose working with multiple subscription that the result of the previous one depends the next?

Update: There seem a problem with Subscription #2. The subscription is not yet complete but I start iterating over the list, which give me a double user list!

Rob
  • 14,746
  • 28
  • 47
  • 65
Reni
  • 85
  • 1
  • 8
  • Did you check the `flatMap` operator? http://stackoverflow.com/questions/36712659/angular-2-two-backend-service-calls-on-success-of-first-service/36712707#36712707 – eko Oct 20 '16 at 10:24
  • Not sure what's the difference between what I did and `flatMap`, or how to use it with my 4 subscriptions |: – Reni Oct 20 '16 at 10:53

1 Answers1

0

Try this.

ngOnInit() {
    this.projectService.getCurrentproject().take(1)
        .flatMap(projectData => {
            return this.af.database.list('/project_roles/'+projectData.$key)
        })
        .flatMap(userMeta => {
            let subs = userMeta.map(projectRole => {
                return Observable.zip([
                    this.af.database.object('/roles/'+projectRole.$value),
                    this.af.database.object('/users/'+projectRole.$key)
                ]).map(([roleData, user]) => {
                    user.role = roleData.$value;
                    return Observable.of(user)
                })
            });
            return Observable.zip(subs)
        })
        .subscribe(users => {
            this.users = users
        })
}

Basically I am composing the subscriptions to get a single observable which emits the users array

Gaurav Mukherjee
  • 6,205
  • 2
  • 23
  • 33
  • Interesting. This is much better organized - but not working. I investigated it and `userMeta` variables is good, but after it nothing is executed (placed console logs everywhere, and they don't show). the merge observables are not executed. – Reni Oct 20 '16 at 13:42
  • found an error... fixed it. the map should return Observable.of(user) instead of user. Observable.zip expects observable array – Gaurav Mukherjee Oct 20 '16 at 13:52
  • I really have no idea why, but the code after `map((roleData, user) => {` is not executed at all. that means the `return Observable.of(user)` is never reached. There are no errors btw – Reni Oct 20 '16 at 14:00
  • It's ok I've been trying to figure those things out for days. The code is still not executed, but if I change your code and add a subscription `.subscribe(data => { })` after `return Observable.of(user) })` it does executed, but `.subscribe(users => {` is not reached – Reni Oct 20 '16 at 14:06
  • please try again.. and instead of subscribe do console log before `Observable.of(user)` – Gaurav Mukherjee Oct 20 '16 at 14:13
  • I did console log everywhere, the console log before `Observable.of(user)` is not showing (and the one before `this.users = users;`) – Reni Oct 20 '16 at 14:15
  • Yeah I watch any change you make and try it – Reni Oct 20 '16 at 14:20