我正在寻找某种最佳实践或模式来处理以下情况:
我想通过以下两种方式合并两个流:
|-------------|
| Transform A |------------>|---------|
|---------|----->|-------------| | |
Stream A----->| Split A | | Combine |-------> ?
|---------|----->|--------------------| | All |
| Transform and | | |
| Combine A (latest) |----->|---------|
| and B (latest) |
Stream B---------------------->|--------------------|
流A和B正在异步生成事件。我想结合A和B的最新信息,并将结果与A之上的计算结果结合起来。
当收到B中的事件时,整个管道将使用该事件中的值以及A中的最新值来运行。
是否有一种优雅的方法来确保在收到A中的事件时,全部合并与基于A中该事件的事件一起运行,并避免在转换A 和转换并合并A和B
答案 0 :(得分:1)
您可以通过将单线程调度程序与去抖动运算符组合在一起来实现:
cases: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Case' }],
这当然不是开箱即用的,您必须弄乱调度程序和测试以使其正确,但是也许这个想法会有所帮助。如果使用防抖为“零”的超时功能感觉有点太过分了,您还可以使用其他签名,以可观察的方式完全控制防抖周期。
但是,如果您的预期用途不是一般情况,并且仅针对上述情况,则可以使用类似以下的方法来简化问题:
class ManualExecutor : Executor {
private val tasks = ArrayDeque<Runnable>()
override fun execute(command: Runnable) = tasks.push(command)
fun runAllTasks() {
while (tasks.isNotEmpty()) {
tasks.pop().run()
}
}
}
val a: Observable<A>
val b: Observable<B>
val scheduler = Schedulers.from(ManualExecutor())
val aTransformed = a.observeOn(scheduler).map { transformA(it) }
val aCombinedWithB = combine(a, b).observeOn(scheduler)
val final = combine(aTransformed, aCombinedWithB).debounce(0)
// some time later....
emitA() // now all the updates are queued in our ManualExecutor
scheduler.runAllTasks() // final will only emit once, not twice!
答案 1 :(得分:0)
使用Observable.Publish(source, x => ...)
可确保您仅拥有source
的一个订阅,但您可以将其用作变量x
的任意次数。这样可以确保您永远不会在source
上遇到任何竞赛情况。
您可以这样使用它:
Func<A, C> transform_A = a => ...;
Func<A, B, D> combine_A_and_B = (a, b) => ...;
Func<C, D, E> combine_all = (c, d) => ...;
IObservable<A> stream_a = ...;
IObservable<B> stream_b = ...;
IObservable<E> query =
stream_a
.Publish(stream_a_published =>
{
var stream_c = stream_a_published.Select(transform_A);
var stream_d = stream_a_published.CombineLatest(stream_b, combine_A_and_B);
return stream_c.CombineLatest(stream_d, combine_all);
});
答案 2 :(得分:0)
基于@tonicsoft的最新评论,其想法是拥有这样的东西:
Flowable<Pair<Long, String>> streamPairA = Flowable.interval(3, SECONDS)
.doOnNext(l -> System.out.println("new value of A: " + l))
.map(l -> new Pair<>(l, "Hello " + l));
Flowable<Long> streamB = Flowable.interval(5, SECONDS)
.doOnNext(l -> System.out.println("new value of B: " + l));
Flowable.combineLatest(streamPairA, streamB, (x, y) -> "--> " + x.value()
+ " (latest A: " + x.key() + ", latest B: " + y + ")")
.subscribe(System.out::println);
Flowable.timer(1, MINUTES) // Just to block the main thread for a while
.blockingSubscribe();