RxJava - 在 map 和 doOnSuccess 中执行长 运行 任务的任何问题

RxJava - any problems with doing long running task in map and doOnSuccess

考虑以下因素

class Dummy {
    private fun firstStep(): Single<String> {
        return Single.just("dafe")
                .subscribeOn(Schedulers.io())
    }
    fun action1() {
        firstStep()
                .map {
                    mapStuff(it)
                }
                .doOnError {
                    println("${Thread.currentThread().name} it")
                }
                .doOnSuccess {
                    someVoidAction(it)
                }
                .flatMap { 
                    return@flatMap anotherStep(it)
                }
                .observeOn(Schedulers.trampoline())
                .subscribe( { result ->
                    println(result)
                }, {
                    it.printStackTrace()
                })
    }
    private fun mapStuff(it: String): Int {
        println("mapStuff on thread ${Thread.currentThread().name}")
        Thread.sleep(2000L)
        return it.length
    }
    private fun someVoidAction(i: Int) {
        println("someVoidAction on thread ${Thread.currentThread().name}")
        Thread.sleep(2000L)
    }
}

我能看到的唯一缺点是:

  1. 它的可读性不强 - 查看动作链,您无法立即判断“mapStuff”和“doVoidAction”实际上是长任务 -运行 就像您如何判断“anotherStep”[=] 30=]
  2. 理论上,一个人可能想为不同的任务使用不同的线程。例如,“mapStuff”可能需要 Schedulers.computation() 而不是 Schedulers.io()。然而,在实践中,Schedulers.io() 在我的项目中有 99% 的时间被使用。那么,我们需要关心吗?
  3. 根据需要,在极少数情况下,我可能想在“mapStuff”或“doVoidAction”上应用 2 秒超时和“错误恢复”逻辑。但话又说回来,这是情境性的,所以在一般情况下,可以像上面那样以非反应性方式执行“mapStuff”或“doVoidAction”吗?

还有其他我没有发现的问题吗?

以 RxJava 方式编写所有内容的缺点是需要更多的工作,具体取决于一个人对 RxJava 的熟练程度(或痴迷程度)。

这里的简单伪代码非常简单,但在现实生活中可能会变得更加复杂:

fun action2() {
        firstStep()
                .flatMap {
                    mapStuffReactive(it)
                }
                .flatMap {
                    return@flatMap doStuffReactive(it)
                }
                .flatMap {
                    return@flatMap anotherStep(it)
                }
                .observeOn(Schedulers.trampoline())
                .subscribe( { result ->
                    println(result)
                }, {
                    it.printStackTrace()
                })
    }

    private fun doStuffReactive(i: Int): Single<Int> {
        return Completable.fromAction {
            println("someVoidAction $i")
        }
                .delay(2L, TimeUnit.SECONDS, Schedulers.io())
                .andThen(Single.just(i))
    }

    private fun mapStuffReactive(it: String): Single<Int> {
        return Single.just(it.length)
                .delay(2L, TimeUnit.SECONDS, Schedulers.io())
    }

Rx Design Guidelines 之后,您永远不应将导致副作用的代码放在 map 中。您应该始终明确显示副作用代码。

导致副作用的代码只应在创建可观察对象时、在订阅中出现,或者很少在 do 运算符中出现。这将使阅读代码的任何人都清楚发生了什么,并且还可以更容易地确定链的哪一部分是可测试的或不可测试的。

do 运算符中的副作用很好,事实上它们是预期的,但是请确保您了解这些副作用会发生在 every 订阅可观察的。 IMO,如果您可以将代码放入订阅中,请改为这样做。