【问题标题】:Different Pipe Based on Filter RxJS基于Filter RxJS的不同管道
【发布时间】:2019-12-23 16:03:56
【问题描述】:

我有以下问题。我想使用 Angular 中的异步管道订阅 observable。但是管道中的数据可能来自不同的数据源,并且管道的外观可能因数据源而异。

现在它的实现方式不起作用,因为我覆盖了this.data$ 的第一个值,因此源 A 永远不会被订阅。

是否可以根据过滤器“拆分”管道?

problem.component.ts:

// Data source A and logic A 
this.data$ = this.service.context.pipe(
  filter(context => context.flag === true),
  switchMap(context => this.dataSourceA(context.id))
  map(data => this.processDataA(data))
);

// Data source B and logic B 
this.data$ = this.service.context.pipe(
  filter(context => context.flag === false),
  switchMap(context => this.dataSourceB(context.id))
  map(data => this.processDataB(data))
);

problem.component.html

<pro-table [data]="data$ | async"></pro-table>

【问题讨论】:

  • 是什么阻止你使用if else 语句

标签: javascript angular typescript rxjs


【解决方案1】:

将逻辑移至您的switchMap()

this.data$ = this.service.context.pipe(
   switchMap(context => context.flag
      ? this.dataSourceA(context.id).pipe(map(d => this.processDataA(d)))
      : this.dataSourceB(context.id).pipe(map(d => this.processDataB(d)))
   )
);

【讨论】:

  • 如果context.flag 不是布尔值而是例如枚举,你将如何解决这个问题?
  • @mafus1,只需 context 上的 switch 确保 eash 分支返回 Observable
  • @mafus1 处理可观察流中的逻辑可能会使源代码变得非常冗长。我有一些运算符可以让你以声明的方式表达一些逻辑。 github.com/reactgular/observables
【解决方案2】:

这是实现您想要的结果的错误方法。你必须接管一个叫做“高阶可观察”的东西:Observable&lt;Observable&lt;T&gt;&gt;。就像一个“高阶函数”(能够根据它的参数产生另一个函数),这个家伙能够根据你所依赖的任何参数化产生另一个Observable

this.service.context.pipe(
  switchMap(context => context.flag ? this.dataSourceA(context.id).pipe(...) : this.dataSourceB(context.id).pipe(...))
);

...一开始可能看起来有点深奥,但实际上并非如此。 \


附:需要记住的重要一点:高阶可观察对象让您以一种奇特的方式参数化您的流:通过处理 流的流

【讨论】:

  • @Reactgular,那是什么?
  • 高阶 observable 是发出另一个 observable 的,然后通常跟一个mergeAll。在您的示例中,这里没有更高的顺序。您的代码确实回答了这个问题。所以我删除了我的反对票,但描述不正确。
  • @Reactgular,你错过了switchMap 实际上是pipe(map(), switchAll()),其中map 是产生Observable&lt;Observable&lt;T&gt;&gt;(即“流的流”)的确切点;这就是“高阶可观察”。
  • @Reactgular,我认为这并不“坏”;我会说它需要更深入的理解。
【解决方案3】:

您可以添加一个Subject,它将捕获许多数据源并订阅它:

    this.data$ = new Subject();
    observer = {
     next(data) { this.data$.next(data) },
     error(msg) { /*handle error*/ }
   };
    // Data source A and logic A 
   this.service.context.pipe(
     filter(context => context.flag === true),
     switchMap(context => this.dataSourceA(context.id))
     map(data => this.processDataA(data))
   ).subscribe(observer);

   this.service.context.pipe(
     filter(context => context.flag === false),
     switchMap(context => this.dataSourceB(context.id))
     map(data => this.processDataB(data))
   ).subscribe(observer);

在这种情况下,尽管您似乎可以使用该标志将其保持在一个块中:

this.service.context.pipe(
     switchMap(context => context.flag ?
         this.dataSourceA(context.id) : this.dataSourceB(context.id)
    )
     map(data => this.processData(data)) // handle both cases
   ).subscribe(observer);

【讨论】:

    猜你喜欢
    • 2018-11-03
    • 2020-09-26
    • 2020-07-27
    • 2020-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-30
    • 1970-01-01
    相关资源
    最近更新 更多