Search code examples
rxjsrxjs-pipeable-operatorsrxjs-observables

RxJs: Can you spread operators as arguments into pipe operator


I have two observable streams which do very separate mapping logic, but then ultimately end with following 3 operators:

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

I want to move the last tap, switchMap, map operators to a common function so I can just apply these within both of my observable streams.

I thought of doing:

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

But I wasn't sure how to spread these operators into the pipe arguments, like:#

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

this errors that there are no overloads that expect 3 or 5 arguments..


Solution

  • You can try use native .apply()

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

    or wrap the list of operator in pipe()

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

    or return higher order function

    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])
          );