Typescript RxJS中tap运算符的输出出现问题

Typescript RxJS中tap运算符的输出出现问题,typescript,rxjs,Typescript,Rxjs,我对下面代码的输出感到困惑,因为take(3)处理应该在渲染10后停止,但仍然从tap操作符获得5、6和9。请参考下面的输出和代码片段 抽头值为空 抽头值20 项目20 抽头值15 项目15 抽头值10 项目10 完成 抽头值5 抽头值6 抽头值9 of(空、20、15、10、5、6、9) .烟斗( 点击(val=>console.log(`Tapped value${val}`)), filterNil(), 采取(3) ) .订阅( item=>console.log(`Renderin

我对下面代码的输出感到困惑,因为take(3)处理应该在渲染10后停止,但仍然从tap操作符获得5、6和9。请参考下面的输出和代码片段

  • 抽头值为空
  • 抽头值20
  • 项目20
  • 抽头值15
  • 项目15
  • 抽头值10
  • 项目10
  • 完成
  • 抽头值5
  • 抽头值6
  • 抽头值9
of(空、20、15、10、5、6、9)
.烟斗(
点击(val=>console.log(`Tapped value${val}`)),
filterNil(),
采取(3)
)
.订阅(
item=>console.log(`Rendering item${item}`),
err=>console.log(err),
()=>console.log('Completed')
);
}
常量filterNil=()=>(来源:可观察)=>
新的可观察对象(观察者=>{
返回source.subscribe({
下一个(值){
如果(值!==未定义&&value!==空){
下一步(值);
}
},
错误(错误){
观察者错误(错误);
},
完成(){
observer.complete();
}
});
});

这个问题的最终答案

此问题的正确答案由提供

我的第一个答案-一个过于简单的答案

您所看到的取决于您的代码是完全同步的,因此
在3次排放后取消订阅
,这在
take(3)
中是隐含的,没有机会运行

看看这个版本

of(null, 20, 15, 10, 5, 6, 9)
      .pipe(
        delay(0),  // >>> intruduce a delay
        tap(val => console.log(`Tapped value ${val}`)),
        filterNil(),
        take(3)
  )
在这里,您引入了一个
延迟
,它使
接受
可以
取消订阅
,因此,您可以看到预期的行为

不是答案,而是更详细的推理

我对这个问题做了更多的调查,发现了一些让我之前的答案有点过于简单的东西

让我们从以下事实开始:
filterNil()
是一个合法的自定义操作符,它应该与
filter(item=>item!==null)
做相同的操作,其中
filter
是由
rxjs/operators
提供的操作符,即由库提供的操作符

现在,如果我们将
管道中的
过滤器(item=>item!==null)
替换为
filterNil()
,我们将得到不同的结果

of(null, 20, 15, 10, 5, 6, 9)
      .pipe(
        tap(val => console.log(`Tapped value ${val}`)),
        filter(item => item !== null),
        take(3)
      )

      .subscribe(
        item => console.log(`Rendering Item ${item}`),
        err => console.log(err),
        () => console.log('Completed')
      );
  }

// the output on the console is

Tapped value null
Tapped value 20
Rendering Item 20
Tapped value 15
Rendering Item 15
Tapped value 10
Rendering Item 10
Completed
这意味着
filter(item=>item!==null)
filterNil()

它们不等价的事实似乎来自于
subscribe
方法
Observable
的实现,该方法与
filterNil
filter
具有某种不同的性质

当使用
filterNil
时,可观察的
subscribe
方法的执行轨迹如下

另一方面,如果我们使用
filter
操作符,
subscribe
方法的执行轨迹如下


因此,
filterNil
operator
属性设置为null,而
filter
operator
属性设置为
filterooperator
似乎驱动了不同的行为。我不清楚背后的原因,值得提出一个新问题。

您的
filterNil
函数仍在运行,因为这是一个不受
take
操作符影响的新观察值。RxJS操作符按顺序运行。您可以将
take
移动到管道中的初始位置,或者我建议不要在过滤函数中创建新的可观察对象

//操作员职位问题
.烟斗(
采取(3)
点击(val=>console.log(`Tapped value${val}`)),
filterNil()
)
//或重因子filterNil运算符
常量filterNilRefactor=()=>{
返回source=>source.pipe(过滤器((值)=>value!==undefined&&value!==null))
}
.烟斗(
点击(val=>console.log(`Tapped value${val}`)),
filterNilRefactor(),
采取(3)
)
of(null, 20, 15, 10, 5, 6, 9)
      .pipe(
        tap(val => console.log(`Tapped value ${val}`)),
        filter(item => item !== null),
        take(3)
      )

      .subscribe(
        item => console.log(`Rendering Item ${item}`),
        err => console.log(err),
        () => console.log('Completed')
      );
  }

// the output on the console is

Tapped value null
Tapped value 20
Rendering Item 20
Tapped value 15
Rendering Item 15
Tapped value 10
Rendering Item 10
Completed