我想创建一个接受S
并返回Observable<T>
的方法,该方法在三个(异步)任务完成后以一个值完成。
这三个任务都在队列上运行,并且他们自己的消费者在不同的线程中。
这就是我的想法:
<S, Subject<T>>
并计算S
的值,并使用Subject<T>
在onNext
中设置,然后调用onComplete()
。< / LI>
<S, Subject<Void>>
并在完成工作后致电onComplete()
。 任务1,2和3可以独立运行,并以随机顺序完成。
现在我有三个主题,一个T
和两个Void
。我想返回第一个,但只有在所有任务完成后才让它发出值T
。这是因为我不希望observable的任何订阅者在完成所有任务之前对T
做任何事情。
组合主题以实现此行为的正确方法是什么?我可以使用CountDownLatch
等轻松地将它们混在一起,但我希望有一种rx-native方式来解决这个问题。
我的计划是通过队列正确的方法使用Subjects作为回调吗?我过去常常使用CompletableFuture<T>
,但我想迁移到RX。
答案 0 :(得分:2)
我不完全确定主题在哪里发挥,但您可以使用When
+ And
+ Then
public IObservable<T> MyMethod<S, T>(S incoming) {
//Create a new plan
return Observable.When(
//Start with Task one which will return an T from an S
Observable.FromAsync(async () => await SomeTaskToTurnSIntoT(incoming))
//Add in Task two which returns a System.Reactive.Unit
.And(Observable.FromAsync(() => /*Do Task 2*/))
//Same for Task 3
.And(Observable.FromAsync(() => /*Do Task 3*/))
//Only emit the item from the first Task.
.Then((ret, _, __) => ret))
//Finally we only want this to process once, then we will reuse the
//existing value for subsequent subscribers
.PublishLast().RefCount();
}
上述内容将等到所有三个项目完成后再发出。需要注意的一点是,在Rx中Void
对象实际上是System.Reactive.Unit
,所以如果没有值,你应该返回它。
答案 1 :(得分:2)
请勿使用Subject
s。而是使用异步调度程序合并observable。所以你有:
T task1(S s);
void task2(S s);
void task3(S s);
然后
<S,T> Observable<T> get(S s) {
return Observable.merge(
Observable.just(s)
.map(x -> task1(x))
.subscribeOn(Schedulers.computation()),
(Observable<T>) Observable.just(s)
.doOnNext(x -> task2(x))
.ignoreElements()
.cast(Object.class)
.subscribeOn(Schedulers.computation()),
(Observable<T>) Observable.just(s)
.doOnNext(x -> task3(x))
.ignoreElements()
.cast(Object.class)
.subscribeOn(Schedulers.computation()))
// wait for completion before emitting the single value
.last();
}
答案 2 :(得分:0)
您可以编写自己的Subject
来为您执行此操作,但由于多种原因通常会气馁。相反,您也可以连接由您的任务生成的三个Observables / Subjects。此操作生成Observable
,它会发出由这些任务生成的所有值,并且仅在所有输入Observable都已完成时才会完成。
由于它们的类型略有不同,您需要使用map()
更改后两个任务生成的Observable的签名。
Observable<T> output = Observable.concat(t1,
t2.map(in -> null).ignoreElements(),
t3.map(in -> null).ignoreElements());
如果您想等待所有订阅者使用生成的值,直到所有Observable都已完成,您可以在此last()
上调用Observable
方法。
Observable<T> output = Observable.concat(t1,
t2.map(in -> null).ignoreElements(),
t3.map(in -> null).ignoreElements()).last();