Maksim Dmitriev
Maksim Dmitriev

Reputation: 6209

Identical Observable inside a switchMap

Please take a look at the following code:

class FooImplTest {

    @Test
    fun sample1() {
        val booleanSubject = BehaviorSubject.create<Boolean>()
        val intSubject = BehaviorSubject.create<Int>()
        val stringSubject = BehaviorSubject.create<String>()

        val combineSecondAndThird = Observable.combineLatest(intSubject, stringSubject,
            { t1, t2 -> Pair(t1, t2) })

        intSubject.onNext(1)
        stringSubject.onNext("my str")

        booleanSubject.onNext(true)

        val o1 = combineSecondAndThird
            .switchMap { pair ->
                val i = pair.first
                val s = pair.second

                booleanSubject.switchMap {
                    intSubject.map { secondVal2 -> Triple(i,
                        "$s:$it", secondVal2) }
                }
            }
            .test()
            .assertValue(Triple( 1, "my str:true", 1))

        intSubject.onNext(3)

        o1.assertValueAt(1, Triple( 3, "my str:true", 3))
            .dispose()
    }

}

I think no need to subscribe to intSubject inside booleanSubject.switchMap:

booleanSubject.map { Triple(i,"$s:$it", i) }

I just wonder if there are any edge cases where the original code will yield a result different from the simplified code.

Upvotes: 0

Views: 52

Answers (1)

Sergej Isbrecht
Sergej Isbrecht

Reputation: 4012

Why would you not just compose all three subjects into combineLatest, just like following example?

@Test
fun sample1() {
    val booleanSubject = BehaviorSubject.create<Boolean>()
    val intSubject = BehaviorSubject.create<Int>()
    val stringSubject = BehaviorSubject.create<String>()

    val combined = Observable.combineLatest(
        intSubject,
        stringSubject,
        booleanSubject,
        Function3<Int, String, Boolean, Triple<Int, String, Int>> { i, s, b ->
            Triple(i, "$s:$b", i)
        })

    intSubject.onNext(1)
    stringSubject.onNext("my str")

    booleanSubject.onNext(true)

    val test = combined
        .test()
        .assertValue(Triple(1, "my str:true", 1))

    intSubject.onNext(3)

    test.assertValueAt(1, Triple(3, "my str:true", 3))
        .dispose()
}

The test passes, as before. When all values are emitted synchronous, it should not matter, becaues combineSecondAndThird#switchMap should always be called first.

Upvotes: 1

Related Questions