Rxjs 如何创建一个从ngrx选择器发出一个值,然后在延迟后再发出另一个值的可观察对象?
给定ngrx选择器:Rxjs 如何创建一个从ngrx选择器发出一个值,然后在延迟后再发出另一个值的可观察对象?,rxjs,ngrx,Rxjs,Ngrx,给定ngrx选择器: store.select('count') 我想创建一个observable,它将发出选择器发出的值,然后在延迟后发出另一个特定值 使用concat不起作用,因为(我假设)选择器没有完成,因此永远不会发出0: this.count$ = concat(store.select('count'), of(0).pipe(delay(2000))); 闪电战: -单击“增量”按钮-当前计数应更改为1,然后在2秒后返回0。下面是使用combinelatetest和Behavi
store.select('count')
我想创建一个observable,它将发出选择器发出的值,然后在延迟后发出另一个特定值
使用concat
不起作用,因为(我假设)选择器没有完成,因此永远不会发出0:
this.count$ = concat(store.select('count'), of(0).pipe(delay(2000)));
闪电战:
-单击“增量”按钮-当前计数应更改为1,然后在2秒后返回0。下面是使用
combinelatetest
和BehaviorSubject
我们将在一个主题中保存一个值,并创建一个计时器,该计时器在2s后发出值0。所以我们有两个观测值,一个立即发射,另一个在2秒后发射。我们将这两者结合起来,效果是一个单一的可观察到的
valueHolderSubject$ = new BehaviorSubject(0);
...
this.count$ = combineLatest([
store.select("count").pipe(
tap(x => this.valueHolderSubject$.next(x)),
tap(() =>
timer(2000).subscribe({
next: () => {
this.valueHolderSubject$.next(0);
}
})
),
map(() => this.valueHolderSubject$.value),
distinctUntilChanged()
),
this.valueHolderSubject$
]).pipe(map(([, x]) => x));
下面是一种使用
组合测试和行为主体
我们将在一个主题中保存一个值,并创建一个计时器,该计时器在2s后发出值0。所以我们有两个观测值,一个立即发射,另一个在2秒后发射。我们将这两者结合起来,效果是一个单一的可观察到的
valueHolderSubject$ = new BehaviorSubject(0);
...
this.count$ = combineLatest([
store.select("count").pipe(
tap(x => this.valueHolderSubject$.next(x)),
tap(() =>
timer(2000).subscribe({
next: () => {
this.valueHolderSubject$.next(0);
}
})
),
map(() => this.valueHolderSubject$.value),
distinctUntilChanged()
),
this.valueHolderSubject$
]).pipe(map(([, x]) => x));
如果要发射存储。选择('count')
值,然后在2秒钟内未接收到发射后将其重置为0
,可以使用创建发射两个值的源:
发出的计数
2000ms后0
的“默认”值
这里的技巧是,如果接收到另一个存储,则不会发出第二个值(0
)。选择('count')
值,因为switchMap
将创建一个新源并“切换”到该值:
this.count$=store.select('count').pipe(
开关映射(计数=>concat(
共(个),
of(0).管道(延迟(2000))
))
);
这是一个工作演示
甚至可能值得创建一个自定义操作符:
this.count$=this.store.select('count').pipe(
重置后延迟(0,2000)
);
导出函数resetAfterDelay(默认值:T,delayMs:number){
返回switchMap((值:T)=>concat(
价值的,
of(默认值)。管道(延迟(延迟毫秒))
));
}
如果要发射存储。选择('count')
值,然后在2秒钟内未接收到发射后将其重置为0
,可以使用创建发射两个值的源:
发出的计数
2000ms后0
的“默认”值
这里的技巧是,如果接收到另一个存储,则不会发出第二个值(0
)。选择('count')
值,因为switchMap
将创建一个新源并“切换”到该值:
this.count$=store.select('count').pipe(
开关映射(计数=>concat(
共(个),
of(0).管道(延迟(2000))
))
);
这是一个工作演示
甚至可能值得创建一个自定义操作符:
this.count$=this.store.select('count').pipe(
重置后延迟(0,2000)
);
导出函数resetAfterDelay(默认值:T,delayMs:number){
返回switchMap((值:T)=>concat(
价值的,
of(默认值)。管道(延迟(延迟毫秒))
));
}
根据我对BizzyBob答案的评论,我得到的结果不可靠。但我使用以下方法对其进行了改进:
this.count$ = merge(
store.select('count'),
store.select('count').pipe(delay(2000), map(_ => 0))
);
参见stackblitz:根据我对BizzyBob答案的评论,我得到的结果不可靠。但我使用以下方法对其进行了改进:
this.count$ = merge(
store.select('count'),
store.select('count').pipe(delay(2000), map(_ => 0))
);
请参阅stackblitz:我想要一个如此简单的解决方案,但我无法让这两个方案都可靠地工作,而且它们在第一次发射后似乎从未工作过。请参见此处修改示例中的my-counter.component.ts:我不确定“可靠工作”是什么意思?我已将控制台日志添加到您的SB示例中,它们似乎都非常有效:|哦,我看到了您的解决方案和您真正想要的。您希望0
在每次store发出后2秒发出。选择('count')
。我没有意识到这一点。我想要一个这样简单的解决方案,但我不能让这两个都可靠地工作,而且它们在第一次发射后似乎永远不会工作。请参见此处修改示例中的my-counter.component.ts:我不确定“可靠工作”是什么意思?我已将控制台日志添加到您的SB示例中,它们似乎都非常有效:|哦,我看到了您的解决方案和您真正想要的。您希望0
在每次store发出后2秒发出。选择('count')
。我没有意识到这一点。感谢这一点,虽然它起作用了,但我还是选择了一个更简单的解决方案,就像我发布的答案一样。感谢这一点,虽然它起作用了,但我选择了一个更简单的解决方案,就像我发布的答案一样。这个解决方案的一个潜在问题是,每次发射后,你总是会发射0
2000ms。如果在2秒内发出多个count
值,则0
值将在2秒内清除新收到的值。请参阅我的更新答案,以了解防止这种情况发生的解决方案。是的,这是一个好问题。我没有深入思考这种情况下的行为。此解决方案的一个潜在问题是,每次发射后,您将始终发射0
2000ms。如果在2秒内发出多个count
值,则0
值将在2秒内清除新收到的值。请参阅我的更新答案,以获得防止这种情况发生的解决方案。是的,这是一个好问题,我对这种情况下的行为没有深入思考。