【问题标题】:Is there an easier, more elegant solution for Observables within RxJS pipes?RxJS 管道中的 Observables 是否有更简单、更优雅的解决方案?
【发布时间】:2019-08-30 21:39:37
【问题描述】:

想象一下,我有一个 observable 给我巧克力饼干,但我不想吃白色的。但是由于我是盲人,所以我必须将它们交给服务来确定给定的 cookie 是否是白色的。但我没有马上得到答案。我宁愿得到另一个 observable。

所以这是我想出的代码,但我真的不喜欢它,我认为应该有一个更简单、更优雅的解决方案:

// 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-of 组合的情况下获得我需要的信息?

【问题讨论】:

    标签: javascript angular typescript rxjs


    【解决方案1】:

    您可以在switchMap 中使用filter 来过滤掉白色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);
    })
    

    【讨论】:

      【解决方案2】:

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

      在使用 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);
        }
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-28
        • 1970-01-01
        • 2023-03-30
        • 2015-07-03
        • 1970-01-01
        • 1970-01-01
        • 2020-10-06
        • 1970-01-01
        相关资源
        最近更新 更多