Rx Js: вы можете распространять операторы в качестве аргументов в оператор канала - PullRequest
2 голосов
/ 10 февраля 2020

У меня есть два наблюдаемых потока, которые делают очень отдельные логики отображения c, но в конечном итоге заканчиваются следующими 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 ..

Ответы [ 2 ]

4 голосов
/ 10 февраля 2020

Вы можете попробовать использовать собственный .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])
      );
0 голосов
/ 10 февраля 2020

Вы можете попробовать реактивный подход (без побочных эффектов, за исключением случаев, когда он действительно изолирован):

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();
...