I'm unable to find a clean way of fetching nested data the rxjs way.
There's an observable returning all users and an observable returning all posts given a user id.
getUsers(): Observable<User[]>
and
getPosts(id: string): Observable<[]>
How would I return a list of users including their posts?
At the moment I prepare the data using 2 nested subscriptions.
nestedFetch() {
this.service.getUsers()
.subscribe(
res => {
res.forEach((user) => {
this.service.getPosts(user.Id).subscribe(
posts => {
user.posts = posts;
this.users.push(user);
},
err => console.log('something went wrong: ' + err)
)
})
},
err => console.log('something went wrong: ' + err)
);
}
I would rather use operators something like this. But how can i return users including their posts?
nestedFetch() {
this.service.getUsers().pipe(
map(users => users.map(u => this.membership.getPosts(u.id))),
mergeMap(posts => forkJoin(posts))
).subscribe(
res => this.posts = posts, //returns only posts but not users
err => console.log('something went wrong: ' + err)
)
}
An inner pipe helps to extend the user by his posts.
this.service.getUsers().pipe(
switchMap(users => {
const postsRequests$ = this.users.map(user => this.service.getPosts(user.id).pipe(
// example for a error catch which would lead to an empty array not breaking the forkJoin
// catchError(err => of([])),
map(posts => ({ ...user, posts })),
));
return forkJoin(postsRequests$);
}),
).subscribe(/* ... */);
Would the subscribe catch errors thrown by the inner pipe?
@F.H. Pipe is just linking together (free-point-style) one or more curried functions. So what you need to know is if
forkJoin()
errors when it's inner observables error. The answer is yes it does. If any of the inner observables error, you never get a result fromforkJoin
, just the error.You can additionally handle errors with the rxjs
catchError
operator, I extended my answer