对于RxJS管道中的Observables,是否有更简单,更优雅的解决方案?

问题描述 投票:2回答:2

想象一下,我有一个可观察的给我巧克力饼干,但我不想吃白色的。但由于我是盲人,我必须将它们交给服务部门,以查明给定的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);
}

虽然这确实有效并且有些合理,但如果你必须将更多的内容封装在一起,那么它真的会变得非常混乱。有没有办法直接过滤observable或映射它,所以我得到了我需要的信息,而不使用那个奇怪的combineLatest组合?

javascript angular typescript rxjs
2个回答
1
投票

您应该将其分解为多个语句。

以这种方式工作将允许您在使用Observable实现复杂的异步工作流时生成更易读,可维护的代码。

重构后,您的代码看起来像这样:

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);
  }

另外,请注意,您并不需要将“Observable”附加到变量名的末尾,因为您已经使用$语法来表示该变量是Observable。


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);
})
© www.soinside.com 2019 - 2024. All rights reserved.