重写嵌套订阅
Rewriting Nested Subscription
我原来的代码很难调试和维护,所以我正在重写我的代码。
原码
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()];
}
}
)
}
)
}
)
}
)
所以基本上,我调用了几个 API,API 的参数基于前一个 API 结果,除了最后一个 API 调用。最后一个 API 调用是关于按特定顺序组织用户。
重写代码
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
}
)
我在实现原始嵌套订阅的最后一点时遇到了问题。重写代码是正确的方法吗?我应该如何编写剩余部分以及我应该使用哪个 RxJS 运算符?
是的,您采用了正确的方法。您应该始终避免嵌套 subscribe
.
这将是您正在寻找的实现:
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();
如果您只想在管道内做一些事情,例如赋值,请使用 tap
运算符。
您在问题中遇到的 flatMap
运算符与 switchMap
运算符有点不同。在此特定示例中,两者都可以正常工作,但通常您将主要使用 switchMap
运算符。
查看此博客以了解不同的映射运算符在 RxJS 中的工作方式:https://blog.angular-university.io/rxjs-higher-order-mapping/
我原来的代码很难调试和维护,所以我正在重写我的代码。
原码
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()];
}
}
)
}
)
}
)
}
)
所以基本上,我调用了几个 API,API 的参数基于前一个 API 结果,除了最后一个 API 调用。最后一个 API 调用是关于按特定顺序组织用户。
重写代码
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
}
)
我在实现原始嵌套订阅的最后一点时遇到了问题。重写代码是正确的方法吗?我应该如何编写剩余部分以及我应该使用哪个 RxJS 运算符?
是的,您采用了正确的方法。您应该始终避免嵌套 subscribe
.
这将是您正在寻找的实现:
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();
如果您只想在管道内做一些事情,例如赋值,请使用 tap
运算符。
flatMap
运算符与 switchMap
运算符有点不同。在此特定示例中,两者都可以正常工作,但通常您将主要使用 switchMap
运算符。
查看此博客以了解不同的映射运算符在 RxJS 中的工作方式:https://blog.angular-university.io/rxjs-higher-order-mapping/