我试图一次从列表中显示消息 1 秒。我无法使用 nextMessage() : Observable<any>{
this.currentMessage.next(this.messages[this.messagePointer++]);
return this.currentMessages;
}
subscribeMessage() : void{
this.currentMessage.pipe(switchMap(_=timer(1000).pipe(map(x=>this.nextMessage())))).subscribe(x=>console.log(x));
}
,因为我需要能够在满足条件后立即清除一条消息并显示下一条消息 1 秒。
到目前为止我有
nextMessage
目前这不会产生任何结果。我的想法是,currentMessage
例程每 1 秒更新一次 this.currentMessage.pipe(tap(x=>console.log(x)),switchMap(_=timer(1000).pipe(map(x=>this.nextMessage())))).subscribe(x=>console.log(x));
Observable,如果在两者之间由外部源更新,则 Timer 将被取消并重新启动。 subscribe 方法目前什么都不输出,但是如果我尝试这个
{{1}}
我以 1 秒的间隔从我的数据输出中看到值。为什么点击有效,但订阅无效。
编辑
这是一个指向 StackBlitz Demo
的链接答案 0 :(得分:0)
问题:switchMap
在内部 observable 发出之前杀死了 observable。
流程如下:
currentMessage
发出消息tap
记录该消息switchMap
启动计时器 (1000)nextMessage()
currentMessage
currentMesage
会发出一条消息(与步骤 1 相同)tap
记录该消息(与第 2 步相同)switchMap
杀死前一个 observable,并启动一个新的计时器 (1000)nextMessage()
,它返回一个可观察对象但它被忽略了,因为它在上一步中被杀死了一个简单的解决方法是将 switchMap
更改为 mergeMap
,但不要忘记在内部 observable 上添加一个 take(1)
,因为您只想拥有一个该 observable 的值:
currentMessage
.pipe(
tap(x => console.log('Tap:' + x)),
mergeMap(_ => timer(1000).pipe(
map(x => nextMessage()),
take(1)
))
)
.subscribe(x => console.log(x));
然而,这很难理解发生了什么......如果你转向一种更具反应性的方法,我认为它会变得更简单。
您说不能使用 interval(1000) 因为您需要根据某些条件进行重置。你为什么不把这个条件作为一个主题,这样你就可以把它写下来?看看这个:
const messageResets = new Subject();
const messages: string[] = ['Message 1', 'Message 2', 'Message 3'];
let messagePointer: number = 0;
console.clear();
messageResets.pipe(
startWith(null),
// Every time we need to clear the current message, we just switchMap to a new interval
switchMap(() => timer(0, 1000).pipe(
map(() => messages[messagePointer++ % messages.length])
))
).subscribe(x => console.log(x));
注意:timer(0, 1000)
与 interval(1000)
相同,但它只是在开始时发出一个值,而 interval 不会。
通常我制作主题只是为了表达流外部的事物:在这种情况下,我希望能够根据我不知道的条件从外部清除当前消息。
但是从长远来看,处理对象以保持某种内部状态总是很痛苦的。