我有一条流媒体。当一个流结束,然后下一个流开始时,我需要发出一个桥接它们的中间事件。这需要在上一个流的最后一个事件之后发生,并且需要改变最后一个事件的状态。基本上,输出流需要如下所示:
Stream 1 - event 1
Stream 1 - event 2
Stream 1 - event 3 (Stream 1 completes)
* My bridging event (Mutation of event 3)
Stream 2 - event 1 etc
答案 0 :(得分:3)
使用最后一个元素的单个连锁变异简单地转换每个内部序列。
IObservable<IObservable<T>> source = ...;
Func<T, T> mutation = ...;
IObservable<T> query = source
.Select(innerSource => innerSource
.Publish(o => o.Concat(o.LastAsync().Select(mutation))))
.Concat();
请注意,这假设每个内部流始终至少有一个项目。
答案 1 :(得分:2)
听起来你可能想要Concat而不是Switch。听起来像一个流结束,你得到一个桥接值,然后你挂钩到下一个流。这是Concat而不是Switch。
使用Switch,您可能会得到:
问题是,如果在旧流完成之前出现新流,则旧流上的LastAsync将不会触发,您将无法获得桥接事件。
如果你使用的是Concat,你的observable将不会切换到流B,直到流A完成,如果你使用Timothy Shields的方法,你将在A结束时得到你的最后一个变异值。
但是,如果您遇到的情况是您希望在新流到达时立即切换,但是您希望在那时进行桥接事件,那么它会更棘手。它可能必须是Timothy Shields答案的改编版本,如:
IObservable<IObservable<T>> source = ...;
Func<T, T> mutation = ...;
IObservable<T> query = source
.Select(innerSource => innerSource
.Publish(o => {
// end this stream when source pushes another value
var stream = o.TakeUntil(source);
return stream.Concat(stream.LastAsync().Select(mutation)));
})
.Concat();
可能有更好/更清洁的方法。使用Rx,总是值得尝试一些看起来很复杂的东西,因为有时候一种方式比其他方式简单得多。