基于过滤器RxJS的不同管道

时间:2019-12-23 16:03:56

标签: javascript angular typescript rxjs

我有以下问题。我想使用Angular中的异步管道订阅一个可观察的对象。但是管道中的数据可以源自不同的数据源,并且管道可以根据数据源看起来有所不同。

现在它的实现方式不起作用,因为我覆盖了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>

3 个答案:

答案 0 :(得分:4)

将逻辑移至您的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)))
   )
);

答案 1 :(得分:0)

这是获得所需结果的错误方法。您必须接管一个称为“高阶可观察”的事物:Observable<Observable<T>>。就像“高阶函数”(能够基于其参数生成另一个函数)一样,此人能够根据您依赖的任何参数化来生成另一个Observable

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

...一开始似乎有点深奥,但实际上不是。 \


P.S。要记住的要点:高阶可观察值让您以一种奇特的方式对流进行参数化:通过处理

答案 2 :(得分:0)

您可以添加一个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);