typescript - Opérateurs pipables combinés avec RxJS/Angular


Est-il possible (je ne trouve rien de complet à ce sujet) de combiner plusieurs opérateurs pouvant être enchaînés dans une seule fonction, afin que je puisse l’enchaîner et la réutiliser dans une méthode différente également ?

Voici la chose :

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

Comment puis-je extraire tout ce qui se trouve à l'intérieur de pipe() afin de pouvoir appeler la même chaîne d'opérateurs à partir d'une autre méthode, qui aurait besoin d'effectuer le même appel http et la logique et la manipulation ultérieurs ?

Ce que j'essaie d'atteindre est :

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

Réponse #1

Vous pouvez utiliser la fonction rxjs pipe (Remarque, c'est une fonction autonome, pas la méthode de l'Observable) pour combiner une séquence d'opérateurs en un opérateur réutilisable.

import { pipe } from "rxjs";
 const customPipable = 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 */)
 )
  this.route.url
  .pipe(customPipable)
  .subscribe()

Voici un article à ce sujet

Réponse #2

Vous pourriez extraire une méthode :

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 */)
      );
}

Et ensuite switchMap vers celui-ci :

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

Sinon, vous pourriez créer un opérateur personnalisé, mais cela semble exagéré pour cet usage :

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