4

我有两个可观察的流,它们执行非常独立的映射逻辑,但最终以以下 3 个运算符结束:

  this.selection
    .pipe(
      ..Custom mapping operators
      tap(_ => this.devicesLoading = true),
      switchMap(d => this.mapService.findLocationForDevices(d)),
      map(loc => marker([loc.latitude, loc.longitude])
    )
    .subscribe(markers => this.plotMarkers(markers));

我想将最后一个tap, switchMap, map运算符移动到一个通用函数中,这样我就可以在我的两个可观察流中应用它们。

我想过这样做:

  private resolveLocationsAndConvertToMarkers = (devices: String[]) => [
    tap(_ => this.devicesLoading = true),
    switchMap((devices: string[]) => this.mapService.findLocationForDevices(devices)),
    map(loc => marker([loc.latitude, loc.longitude])
  ];

但我不确定如何将这些运算符传播到管道参数中,例如:#

      this.selection
        .pipe(
          // Custom mapping operators
          ... this.resolveLocationsAndConvertToMarkers
        )
        .subscribe(markers => this.plotMarkers(markers));

这个错误there are no overloads that expect 3 or 5 arguments..

4

3 回答 3

5

您可以尝试使用原生.apply()

this.selection
    .pipe.apply(null,this.resolveLocationsAndConvertToMarkers)

或将运算符列表包装在pipe()

  private resolveLocationsAndConvertToMarkers = (devices: String[]) => pipe(
    tap(_ => this.devicesLoading = true),
    switchMap((devices: string[]) => this.mapService.findLocationForDevices(devices)),
    map(loc => marker([loc.latitude, loc.longitude])
  );

或返回高阶函数

private resolveLocationsAndConvertToMarkers = (devices: String[]) => source=>source.pipe(
        tap(_ => this.devicesLoading = true),
        switchMap((devices: string[]) => this.mapService.findLocationForDevices(devices)),
        map(loc => marker([loc.latitude, loc.longitude])
      );
于 2020-02-10T12:18:34.243 回答
0

我希望这个答案能帮助任何偶然发现这个问题的人。接受的答案对我来说并不完全有效,主要原因null是作为第一个参数.apply()而不是我的可观察函数再次传递。这是一个类似于我在项目中成功实现的示例。

private pipeActions = [
   filter(...),
   map(...),
];

private myObservable = combineLatest(...);

doThing(): Observable<any> {
   return this.myObservable
      .pipe.apply(this.myObservable, [...this.pipeActions]);
}

doOtherThing(): Observable<any> {
   return this.myObservable
      .pipe.apply(
         this.myObservable,
         [...this.pipeActions, map(...)], // Do something additionally after my list of pipe actions
      );
}
于 2021-08-17T16:28:35.953 回答
0

您可以尝试一种反应性方法(除非真正隔离,否则没有副作用):

const preSelection$ = this.selection
  .pipe
  //..Custom mapping operators
  ();

const selection$: Observable<Marker> = preSelection$.pipe(
  switchMap(preSelection =>
    concat(
      of(null),
      of(preSelection).pipe(
        switchMap(d => this.mapService.findLocationForDevices(d)),
        map(loc => marker([loc.latitude, loc.longitude]))
      )
    )
  ),
  shareReplay({ bufferSize: 1, refCount: true })
);

const isLoading$: Observable<boolean> = selection$.pipe(map(x => !!x));

const sideEffectUpdatePlotMarkers$ = selection$.pipe(
  tap(markers => this.plotMarkers(markers))
);

// isolate `subscribe` calls and side effects as much as possible
sideEffectUpdatePlotMarkers$.subscribe();
于 2020-02-10T12:26:48.227 回答