Concurrency 将流拆分,然后与RX组合
我正在寻找某种最佳实践或模式来处理以下情况: 我有两个流,我想以以下方式组合:Concurrency 将流拆分,然后与RX组合,concurrency,rxjs,rx-java,rx-java2,system.reactive,Concurrency,Rxjs,Rx Java,Rx Java2,System.reactive,我正在寻找某种最佳实践或模式来处理以下情况: 我有两个流,我想以以下方式组合: |-------------| | Transform A |------------>|---------| |---------|----->|-------------| | | Stream A-----&g
|-------------|
| 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和转换并使用
Observable.Publish组合A和B
之间的竞争条件(来源,x=>)确保您只有一个订阅源代码
,但您可以将其作为变量x
任意多次使用。它确保您永远不会在源代码上获得任何竞争条件
您可以这样使用它:
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);
});
Func变换_A=A=>。。。;
Func combine_A_和_B=(A,B)=>。。。;
Func combine_all=(c,d)=>。。。;
可观测流_a=。。。;
可观测流_b=。。。;
可观测查询=
溪流
.Publish(stream\u a\u published=>
{
var stream_c=stream_a_published.选择(transform_a);
var stream_d=stream_a_published.CombineTest(stream_b,combine_a_and_b);
返回流c.CombineTest(流d,合并所有);
});
您可以通过将单线程调度程序与debounce操作符相结合来实现这一点:
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!
根据@tonicsoft的最新评论,我们的想法是:
Flowable streamPairA=可流动。间隔(3秒)
.doOnNext(l->System.out.println(“A的新值:“+l))
.map(l->新对(l,“Hello”+l));
可流动流量B=可流动。间隔(5秒)
.doOnNext(l->System.out.println(“B:+l的新值”);
可流动的组合测试(streamPairA,streamB,(x,y)->“-->”+x.value()
+“(最新的A:“+x.key()+”,最新的B:“+y+”)
.subscribe(System.out::println);
Flowable.timer(1,分钟)//只是暂时阻塞主线程
.阻止订阅();
这实际上取决于当只有A
或只有B
发出时,您想要什么行为。否则,withLatestFrom
或CombineTest
应该是您要查找的。当只有B到达时,我希望与A的最新版本合并。当只有A到达时,我希望B的最新版本与A的当前版本合并,但我需要避免竞争条件,导致将A的当前值与基于A的先前值的计算相结合。是的,但是如果B
到达并且还没有A
呢?在这种情况下,我同意的标准行为是使用最新的from。我不太关心这个问题,而更关心的是在两个派生流中获得相同版本的A的问题,这两个派生流基于将图片保存为图形,我猜您的问题是其中有一个菱形,您试图避免在菱形的叶节点处获得双重更新。用现成的rx很难做到这一点。您可以操纵调度器和解Bounce来获得这种行为。我已经开始用一个图书馆来做这个实验:它还没有真正准备好被消费,但它可能会给你一些想法。
|-----------------------|
Stream A----->| map A to |
| pair(A, transform(A)) |
|-----------------------|
|
|----->|--------------------|
| Combine A, t(A) |
| and B (latest) |--> ?
| into 3-tuple |
Stream B---------------------->|--------------------|