My original code is difficult to debug and maintain, so I'm rewriting my code.
Original Code
this.userService.getLocationId(id).subscribe(
(locationId) => {
this.userService.getUserParams(locationId).subscribe(
(params) => {
// This API would store users to Akita Store
this.userService.getUsers(params).subscribe()
// Get data from Akita Store
this.users$.subscribe(
(users) => {
this.users = [...users]
this.userService.putSomeUserFirst().subscribe(
(data) => {
if (data === true) {
this.users.unshift(user)
this.users = [...new Map(this.users.map(agent => [user.id, user])).values()];
}
}
)
}
)
}
)
}
)
So basically, I am calling several API and the parameters for the API are base on the previous API result except the last API call. The last API call is about organizing users in a certain order.
Rewrote Code
this.userService.getLocation(id).pipe(
// Don't know which RxJS operator I should be using
flatMap((locationId) => {
if (locationId) {
return this.userService.getUserParams(locationId)
}
}),
flatMap((params) => {
return this.userService.getUser(params)
}),
flatMap(() => {
return this.users$
})
).subscribe(
(users) => {
this.users = users
}
)
I have trouble on implementing the last bit of the original nested subscription. Is the rewrote code a right approach? How should I write the remaining part and which RxJS operator should I be using?
Yes, you are taking the right approach. You should always avoid nested subscribe
.
This will be the implementation that you are looking for:
this.userService.getLocationId(id).pipe(
switchMap((locationId) => this.userService.getUserParams(locationId)),
switchMap((params) => this.userService.getUsers(params)),
switchMap(() => this.users$),
tap((users) => this.users = [...users]),
switchMap(() => this.userService.putSomeUserFirst()),
tap((data) => {
if (data === true) {
this.users.unshift(user);
this.users = [...new Map(this.users.map(agent => [user.id, user])).values()];
}
})
).subscribe();
Use tap
operator when you just want to do something inside the pipeline, like assign the value.
flatMap
operator that you had in the question is bit different from the switchMap
operator. In this specific example both will work fine, but generally you will mostly be using switchMap
operator.
Have a look at this blog to understand how different mapping operators work in RxJS: https://blog.angular-university.io/rxjs-higher-order-mapping/