【发布时间】:2020-01-05 09:48:28
【问题描述】:
我正在一个使用 Angular 的项目中工作,使用 NgRx 通过动作和减速器来操纵状态。我在这里看到的一个通用代码用于在订阅中调用订阅(我知道这通常是错误的,但我不明白为什么,因为它有效)。 This question 完美地解释了如何处理这个问题,但我的情况 - 我认为 - 略有不同,因为我需要先抢一块 NgRx 商店。
我目前正在做的事情如下:
this.store.pipe(
take(1),
select(userProfile) // <-- take data from the NgRx store
).subscribe(currentUser => {
this.loggedUser = currentUser;
this.achievementService.getAchievement(
(achievment: Achievement) =>
achievement.id === currentUser.achId
).subscribe(
response => {
// ... more code
this.categoryService.getCategory(response.id).subscribe(
category=> {
// ... more code
}
);
}
);
如您所见,我需要在下一个订阅中使用每个订阅的结果,但首先我需要获得一块 NgRx 存储。您将如何重构这部分代码,使其不会使用多个 Observable.subscribe?另外,你能解释一下在另一个内部调用订阅时可能出现的潜在问题吗?
解决方案
@ngfelixl 提出的解决方案可行,但我想在接受之前花一些时间来指定几件事。首先,如果您在 switchMap 中有多行代码,则必须显式返回 observable:
switchMap(currentUser => {
this.loggedUser = currentUser;
return this.achievementService.getAchievement(
(achievment: Achievement) =>
achievement.id === currentUser.achId
);
})
其次,您仍然需要最终订阅(这是您将使用的唯一订阅)。这是完整的代码示例:
this.store.pipe(select(userProfile)).pipe(
switchMap(currentUser => {
this.loggedUser = currentUser;
return this.achievementService.getAchievement(...);
}),
switchMap(achievement => this.categoryService.getCategory(achievement.id))
).subscribe(category => ...)
【问题讨论】:
-
switchMap 总是希望您返回一个 observable,因为您切换了流。在一行中,关键字 return 被省略了。当使用 observables 时,你总是会有订阅,因为没有订阅者,生产者是无用的。当您遇到将一个 observable 的输出用作第二个 observable 的输入的问题时,SwitchMap 通常是首选解决方案。
-
不客气,编码愉快 :-)
标签: angular typescript ngrx