想象一下,我可以给我巧克力饼干,但是我不想吃白色的。但是由于我是盲人,所以我必须将它们交给服务,以查找给定的cookie是否为白色。但是我没有立即得到答案。我宁愿再观察一个。
这是我想出的代码,但是我真的不喜欢它,我认为应该有一个更简单,更优雅的解决方案:
// pipe the observable
chocolateCookieObservable$.pipe(
// use a switchMap to create a new stream containing combineLatest which combines...
switchMap((chocolateCookie: ChocolateCookie) => combineLatest(
// an artificially created stream with exactly one cookie...
of(chocolateCookie),
// and the answer (also an observable) of my cookie service
this.chocolateCookieService
.isChocolateCookieWithWhiteChocolate(chocolateCookie),
// so I get an observable to an array containing those two things
)),
// filtering the resulting observable array by the information contained in
// the array (is the cookie white)?
filter(([chocolateCookie, isWhite]: [ChocolateCookie, boolean]) => !isWhite),
// mapping the array so that I can throw away the boolean again, ending up
// with only the now filtered cookies and nothing more
map(([chocolateCookie]: [ChocolateCookie, boolean]) => chocolateCookie),
).subscribe((chocolateCookie: ChocolateCookie) => {
this.eat(chocolateCookie);
}
尽管这确实可行并且在一定程度上是合理的,但是如果您必须将更多的封装在一起,这确实会造成极大的混乱。没有任何方法可以直接过滤可观察对象或对其进行映射,以便我无需使用奇怪的CombineLatest-of组合即可获取所需的信息?
答案 0 :(得分:1)
您可以在filter
内使用switchMap
来过滤出白色Cookie,然后将响应从服务映射回Cookie
这里有个例子:
chocolateCookieObservable$.pipe(
switchMap((chocolateCookie: ChocolateCookie) =>
// async test if its white
this.chocolateCookieService
.isChocolateCookieWithWhiteChocolate(chocolateCookie)
.pipe(
// filter out white cookies
filter(isWhite => !isWhite),
// map back from isWhite to the cookie
mapTo(chocolateCookie)
)
)
).subscribe((chocolateCookie: ChocolateCookie) => {
// mmm, cookies!!!
this.eat(chocolateCookie);
})
答案 1 :(得分:1)
您应该将此细分为多个语句。
以这种方式工作,将使您在使用Observables实现复杂的异步工作流时,可以生成更具可读性,可维护性的代码。
重构后,您的代码将如下所示:
const isWhite$ = chocolateCookie$.pipe(
switchMap((chocolateCookie: ChocolateCookie) => this.chocolateCookieService.isChocolateCookieWithWhiteChocolate(chocolateCookie)),
);
chocolateCookie$.pipe(
withLatestFrom(isWhite$),
filter(([chocolateCookie, isWhite]: [ChocolateCookie, boolean]) => !isWhite),
map(([chocolateCookie]: [ChocolateCookie, boolean]) => chocolateCookie),
).subscribe((chocolateCookie: ChocolateCookie) => {
this.eat(chocolateCookie);
}
另外,请注意,您实际上并不需要在变量名称的末尾附加“可观察的”,因为您已经在使用$语法表示变量是可观察的。