簡體   English   中英

如何在 RxJava2 中鏈接兩個 Completable

[英]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()使函數調用像SingleObservable的映射函數一樣延遲(或者最好讓它在您點擊訂閱之前沒有任何反應 - 這是一個很好的約定,並在官方 Rx 中使用庫以及我遇到的任何 Rx 擴展,對於高級用戶,這僅指冷完成,但大多數人可以忽略它)。
  • concat(a, b)a.andThen(b)之間的唯一區別是語法

一些例子:

  • foo(a).andThen(bar(b))將:

    1. 調用foo(a)
    2. 即使步驟1返回的可完成項返回錯誤,也立即調用bar(b)
    3. 訂閱第1步返回的任何內容
    4. 僅當最后一步成功完成時才會訂閱bar(b)的結果
  • foo(a).andThen(Completable.defer(() -> bar(b))將:

    1. 調用foo(a)
    2. 訂閱步驟1的結果
    3. 只有當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”行只會在有人訂閱doThingAdoThingB方法時被調用。

這里的第二個概念是 andThen 運算符將如何處理錯誤。 在上面的例子中,如果doThingA() completable 最終出現錯誤,流將結束並且不打印“調用流 B”行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM