Search code examples
angulartypescriptrxjsrxjs-pipeable-operators

Combined pipable operators with RxJS / Angular


Is is possible (I can't find anything comprehensive on this) to combine multiple pipable operators in one function, so I can pipe it and re-use in a different method as well?

Here is the thing:

public ngOnInit(): void {
      this.route.url
            .pipe(
                switchMap( (ids: UrlSegment[]) => /* http call */),
                tap(result => /* setting a variable within a service */),
                tap(result => /* some more manipulating and logic */),
                map(result => /* setting a _this_ variable */)
            )
            .subscribe( () => {
                /* some other async tasks, which depend on _this_ variables */
                this.cdr.detectChanges();
            });
      }

How do I extract everything within pipe() so I can call the same chain of operators from a different method, which would need to perform the same http call and subsequent logic and manipulating?

What I try to achieve is:

 this.route.url
   .pipe(
       this.combinedPipableMethod(url: UrlSegment[])
   )
   .subscribe()

Solution

  • You could extract a method:

    getData(ids: UrlSegment[]) {
       return this.http.get(/* url construction logic */)
          .pipe(
             tap(result => /* setting a variable within a service */),
             tap(result => /* some more manipulating and logic */),
             map(result => /* setting a _this_ variable */)
          );
    }
    

    And then switchMap to it:

    public ngOnInit(): void {
       this.route.url
          .pipe(
              switchMap(this.getData),
           )
           .subscribe( () => {
              /* some other async tasks, which depend on _this_ variables */
              this.cdr.detectChanges();
           });
    }
    

    Otherwise, you could make a custom operator but it seems like overkill for this purpose:

    const combinedPipableMethod = () => {
      return source => defer(() => {
        return source.pipe(
           switchMap((ids: UrlSegment[]) => /* http call */),
           tap(result => /* setting a variable within a service */),
           tap(result => /* some more manipulating and logic */),
           map(result => /* setting a _this_ variable */)
        )
      })
    }
    
    public ngOnInit(): void {
       this.route.url
          .pipe(
              combinedPipableMethod(),
           )
           .subscribe( () => {
              /* some other async tasks, which depend on _this_ variables */
              this.cdr.detectChanges();
           });
    }