Typescript RxJS中tap运算符的输出出现问题
我对下面代码的输出感到困惑,因为take(3)处理应该在渲染10后停止,但仍然从tap操作符获得5、6和9。请参考下面的输出和代码片段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
- 抽头值为空
- 抽头值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