【问题标题】:Combined pipable operators with RxJS / Angular将 pipable 运算符与 RxJS / Angular 相结合
【发布时间】:2020-03-06 22:56:41
【问题描述】:

是否有可能(我找不到任何全面的内容)在一个函数中组合多个 pipable 运算符,这样我也可以通过管道传输它并以不同的方法重复使用?

事情是这样的:

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

如何提取 pipe() 中的所有内容,以便我可以从不同的方法调用相同的运算符链,这需要执行相同的 http 调用以及后续逻辑和操作?

我试图实现的是:

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

【问题讨论】:

  • 我不确定您为什么要在地图中设置类成员值(_this_ 变量)。您应该根据map 中的给定排放创建新数据。不执行副作用。感觉你的map 中的代码属于你的subscribe 回调。
  • 你是对的。我也应该把它改成tap
  • 我认为您应该在subscribe 回调中执行这些操作。不要真正看到拥有三个tap 的意义。我个人只使用tap 进行日志记录。
  • 我真的不知道tapwas 的最佳实践或最初意图是什么。正如我所看到的 - 如果这是一些设置并忘记,它在tap 中更清晰。我在最近参与的一个项目中选择了这种风格,并且非常喜欢它。在subscribe,我确实有更多的函数调用,它们处理this 上下文,但是在另一个函数中没有出现重用这个pipe,所以我会保持原样。
  • 当我们在做的时候——你能看看这个问题吗? :) stackoverflow.com/questions/58746929/…

标签: angular typescript rxjs rxjs-pipeable-operators


【解决方案1】:

您可以使用 rxjs pipe(注意,它是一个独立的函数,而不是 Observable 的方法)函数将一系列运算符组合成一个可重用的运算符。

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

Here is an article about it

【讨论】:

    【解决方案2】:

    您可以将链存储在Subject 中,然后只需在主题上调用next() 即可强制管道运行

    //Subject for storing pipeline
    loadDataSubject = new Subject();
    
    ngOnInit() {
      loadDataPipe(this.loadDataSubject).subscribe(
         /* some other async tasks, which depend on _this_ variables */
         this.cdr.detectChanges();
      )
    }
    
    loadDataPipe(source) {
      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 */)
      )
    }
    

    现在,您可以随时使用next() 再次调用管道运行:

     ....
     this.loadDataSubject.next();
     ....
    

    【讨论】:

      【解决方案3】:

      你可以提取一个方法:

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

      然后switchMap 给它:

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

      否则,您可以创建一个自定义运算符,但为此目的似乎有点矫枉过正:

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

      【讨论】:

      • 两种变体听起来都不错 - this 上下文怎么样?第一个不知道任何this了...
      • 没关系。我已将符号更改为 switchMap( urls => this.getData(urls)) 以保留上下文
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-27
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      相关资源
      最近更新 更多