[英]How to chain two Completable in RxJava2
我有兩個 Completable。 我想做以下場景:如果第一個 Completable 到達 onComplete ,則繼續第二個 Completable。 最終結果將是第二個 Completable 的 onComplete。
當我有 Single getUserIdAlreadySavedInDevice()和 Completable login()時,我就是這樣做的:
@Override
public Completable loginUserThatIsAlreadySavedInDevice(String password) {
return getUserIdAlreadySavedInDevice()
.flatMapCompletable(s -> login(password, s))
}
您正在尋找andThen
運算符。
返回一個 Completable,它首先運行這個 Completable,然后是另一個 Completable。
firstCompletable
.andThen(secondCompletable)
通常,此運算符是Completable
flatMap
的“替代品”:
Completable andThen(CompletableSource next)
<T> Maybe<T> andThen(MaybeSource<T> next)
<T> Observable<T> andThen(ObservableSource<T> next)
<T> Flowable<T> andThen(Publisher<T> next)
<T> Single<T> andThen(SingleSource<T> next)
TL;DR:其他答案忽略了一個微妙之處。 使用doThingA().andThen(doThingB())
如果你想相當於concat
,使用doThingA().andThen(Completable.defer(() -> doThingB())
如果你想在相當於flatMap
。
flatMap()
是merge()
的映射版本concatMap()
是concat()
的映射版本Completable
您需要defer()
使函數調用像Single
或Observable
的映射函數一樣延遲(或者最好讓它在您點擊訂閱之前沒有任何反應 - 這是一個很好的約定,並在官方 Rx 中使用庫以及我遇到的任何 Rx 擴展,對於高級用戶,這僅指冷完成,但大多數人可以忽略它)。concat(a, b)
和a.andThen(b)
之間的唯一區別是語法一些例子:
foo(a).andThen(bar(b))
將:
foo(a)
1
返回的可完成項返回錯誤,也立即調用bar(b)
1
步返回的任何內容bar(b)
的結果 foo(a).andThen(Completable.defer(() -> bar(b))
將:
foo(a)
1
的結果foo(a)
返回的 Completable 成功時才調用bar(b)
我將省略對merge()
的處理,因為它變得有點復雜,但長話短說,如果您想要“並行”,就可以調用它。
上面的答案有點正確,但我發現它們具有誤導性,因為它們錯過了關於急切評估的微妙之處。
doThingA().andThen(doThingB())
將立即調用doThingB()
但僅在doThingB()
返回的doThingA()
完成時訂閱doThingB()
返回的doThingA()
。
doThingA().andThen(Completable.defer(() -> doThingB())
doThingB()
只有在事情 A 完成后才會調用doThingB()
。
只有當doThingB()
在 subscribe 事件之前有副作用時,這才是重要的。 例如Single.just(sideEffect(1)).toCompletable()
在訂閱事件(真正的冷觀察)之前沒有副作用的實現可能是Single.just(1).doOnSuccess(i -> sideEffect(i)).toCompletable()
。
在這種情況下,A 是一些驗證邏輯, doThingB()
立即啟動異步數據庫更新,完成 VertX ObservableFuture。 這不好。 可以說doThingB()
應該寫成只在訂閱時更新數據庫,我將來會嘗試以這種方式設計東西。
嘗試
Completable.concat
Returns a Completable which completes only when all sources complete, one after another.
http://reactivex.io/RxJava/javadoc/io/reactivex/Completable.html#concat(java.lang.Iterable)
我遇到了同樣的問題,我使用運算符 .concactWith 使其工作。 就我而言,我有兩個 Completable 類型的樂趣。
fun makeTwoThings(): Completable {
makeFirstThing().concatWith(makeSecondThing())
}
fun makeFirstThing(): Completable{
//TODO()
}
fun makeSecondThing(): Completable{
//TODO()
}
請注意,這里有更多選票的答案有點誤導。 看下面的例子,我的想法是展示一些測試場景,並展示帶有操作符andThen
邏輯是andThen
表現的。
private fun doThingAFail(): Completable {
print("Do thingA Called\n")
return Completable.fromCallable {
print("calling stream A\n")
throw(Exception("The excep"))
}
}
private fun doThingB(): Completable {
print("Do thingB Called\n")
return Completable.fromCallable {
print("calling stream B\n")
}
}
private fun doThingA(): Completable {
print("Do thingA Called\n")
return Completable.fromCallable {
print("calling stream A\n")
}
}
請注意以下測試:
@Test
fun testCallAPlusB() {
doThingA().andThen(doThingB())
}
快速說明:請注意,我們沒有訂閱此代碼段中的這些 Completable。
輸出將是:
Do thingA Called
Do thingB Called
對於測試:
@Test
fun theTestSubscribe() {
doThingA().andThen(doThingB()).subscribe()
}
輸出將是:
Do thingA Called
Do thingB Called
calling stream A
calling stream B
最后,如果第一個 Completable 失敗,第二個 Completable 將不會被執行。
@Test
fun theTestFailThingA() {
doThingAFail().andThen(doThingB()).subscribe()
}
輸出將是:
Do thingA Called
Do thingB Called
calling stream A
這里的關鍵概念是方法內部的邏輯和 observable 內部的邏輯不是同時執行的。 一旦我們調用doThingA()
和doThingB()
方法,就會打印“Do thingA Called”和“Do thingB Called”行。 而“調用流 A”和“調用流 B”行只會在有人訂閱doThingA
和doThingB
方法時被調用。
這里的第二個概念是 andThen 運算符將如何處理錯誤。 在上面的例子中,如果doThingA()
completable 最終出現錯誤,流將結束並且不打印“調用流 B”行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.