在RxJS中,如何防止操作员在源可观测数据没有';你没有吗?
我有三个可观察对象,在RxJS中,如何防止操作员在源可观测数据没有';你没有吗?,rxjs,rxjs6,Rxjs,Rxjs6,我有三个可观察对象,foo$、bar$和baz$,我将它们合并在一起形成另一个可观察对象。这是预期的工作: 流以>> 每个值一个接一个地发出 流以{ console.log(str); }); const{merge,of}=rxjs;const{startWith,endWith}=rxjs.operators来自startWith的文档: 返回一个Observable,该Observable在开始发出源Observable发出的项之前发出您指定为参数的项 因此,startWith和end
foo$
、bar$
和baz$
,我将它们合并在一起形成另一个可观察对象。这是预期的工作:
- 流以
>>
- 每个值一个接一个地发出
- 流以
{ console.log(str); });代码>
const{merge,of}=rxjs;const{startWith,endWith}=rxjs.operators代码>来自
的文档: 返回一个Observable,该Observable在开始发出源Observable发出的项之前发出您指定为参数的项 因此,startWith
和startWith
将始终运行 我不知道您期望的结果应该是什么,但是如果您只想为每个发出的值连接字符串,您可以使用endWith
或map
运算符 编辑: 将switchMap
映射到concat每个值的示例:
constfoo$=of('foo').pipe(filter(()=>false)); const bar$=of('bar').pipe(过滤器(()=>false)); const baz$=of('baz').pipe(过滤器(()=>false));
merge(foo$、bar$、baz$).pipe(map(v=>`>>>${v}实现这一点的一种方法是使用对:source$.pipe( //将流上的所有事件转换为通知 具体化(), //仅当元素存在时才换行 开关映射((事件、索引)=>{ //如果它的第一个事件和一个值 如果(索引===0&&event.kind==='N'){ const startingNotification=新通知('N','>>>',未定义); 返回(启动通知、事件); } //如果它是一个完成事件而不是第一个事件 如果(索引>0&&event.kind=='C'){
const endingNotification=new Notification('N','第一个条件很简单。您只需使用
预先设置第一个发射:concatMap
第二个条件更为棘手。您基本上想要的是与mergeMap((v, index) => index === 0 ? of('>>>', v) : of(v))
相反的右键。我想不出任何简单的解决方案,因此我可能会使用defaultIfEmpty
,如果它是第一个也是唯一的发射,则忽略发射(这意味着源刚刚完成,没有发射任何东西):endWith
endWith('>>,v):of(v)),
endWith(“您可以将合并的可观察对象分配给一个变量,从流中获取第一个元素,然后映射到至少发出一个值时要执行的可观察对象const foo$=of('foo').pipe(过滤器(()=>false)) 常量条$=的('bar')。管道(过滤器(()=>false)) const baz$=of('baz').pipe(过滤器(()=>false)) const merged$=合并(foo$、bar$、baz$); 合并的$管道( 以(1)为例, switchMap(()=>合并的$.pipe( startWith('>>'),
结束(“我知道所有答案都是通过组合运算符来完成的,但是只使用运算符来解决这个问题有点棘手,为什么不创建自己的可观察的运算符呢?我认为这个解决方案是最容易理解的。没有隐藏的聪明,没有复杂的运算符组合,没有子运算符描述重复 解决方案:constfoo$=of('foo')/.pipe(filter(()=>false)); const bar$=of('bar')/.pipe(过滤器(()=>false)); const baz$=of('baz')/.pipe(过滤器(()=>false)); 函数wrapIfOnEmit$(…obs){ 返回新的可观察对象(观察者=>{ 让我来; 常量订阅=合并(…obs)。订阅((数据)=>{ 如果(!hasEmission){ 观察者。下一个('>>'); a=真; } 下一步(数据); }, (错误)=>观察者错误(错误), () => {
if(hasEmissed)observer.next('我的预期输出是if
不发出值,那么我就不应该看到merge()
也不应该看到>
我有一个可能产生值或可能不产生值的流。当流完成时,我需要连接发出的字符串,然后才应用前缀/后缀。我可以在管道外部应用我的词缀,但我想知道是否可以将这种行为添加到其中。希望是澄清了一点。@customcommander我添加了一个示例,希望这就是您想要的。谢谢,但这不会将词缀应用于每个发出的值吗?我需要发出
,并且>
我可以看到混淆,我已经编辑了我的问题。对不起。我想,另一种方法是将
与throwIfEmpty
和startWith一起使用
,然后是endWith
,这将抑制“空错误”并通过原始错误。但需要测试此方法。谢谢您的回答。当catchError
完全不发射时,此方法有效。否则,如果其中一个合并的可观察对象发射值,则无论是合并的$
还是开始时间
都不会发射其值。@customcommander否,只要其中一个合并的可观察对象发射值发出一个值,您正在将该值映射到另一个流,该流使用结束时间
和startWith
发出。请查看我的堆栈闪电并删除endWith
对于其中一个观测值。抱歉。我确实尝试过,但它不起作用,但当我从您的答案中重写代码时,我一定是在某个地方打错了。我复制/粘贴了您的代码,它就起作用了;)我非常喜欢这个答案。我将等待更多的答案(@customcommander,fridoo,这导致了对.pipe(过滤器(()=>false))
的双重订阅。因此,需要在合并$
@kos内部执行switchMap
。我的理解是concat
将从可观察的源取消订阅。因此,除非我弄错了,否则应该没问题。谢谢你。我感觉来自@fridoo的答案更为惯用。+1思想请注意,对于第一次发射可能被吞没的“热”观测,该解决方案可能会产生不同的结果。我猜您可以将第一次发射添加到switchMap
startWith<
endWith('<<<'), filter((v, index) => index !== 0 || v !== '<<<'),
const foo$ = of('foo');//.pipe(filter(() => false)); const bar$ = of('bar');//).pipe(filter(() => false)); const baz$ = of('baz');//.pipe(filter(() => false)); merge(foo$, bar$, baz$).pipe( mergeMap((v, index) => index === 0 ? of('>>>', v) : of(v)), endWith('<<<'), filter((v, index) => index !== 0 || v !== '<<<'), ).subscribe(console.log);