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)
}
}
我能看到的唯一缺点是:
- 它的可读性不强 - 查看动作链,您无法立即判断“mapStuff”和“doVoidAction”实际上是长任务 -运行 就像您如何判断“anotherStep”[=] 30=]
- 理论上,一个人可能想为不同的任务使用不同的线程。例如,“mapStuff”可能需要
Schedulers.computation()
而不是 Schedulers.io()
。然而,在实践中,Schedulers.io()
在我的项目中有 99% 的时间被使用。那么,我们需要关心吗?
- 根据需要,在极少数情况下,我可能想在“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,如果您可以将代码放入订阅中,请改为这样做。
考虑以下因素
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)
}
}
我能看到的唯一缺点是:
- 它的可读性不强 - 查看动作链,您无法立即判断“mapStuff”和“doVoidAction”实际上是长任务 -运行 就像您如何判断“anotherStep”[=] 30=]
- 理论上,一个人可能想为不同的任务使用不同的线程。例如,“mapStuff”可能需要
Schedulers.computation()
而不是Schedulers.io()
。然而,在实践中,Schedulers.io()
在我的项目中有 99% 的时间被使用。那么,我们需要关心吗? - 根据需要,在极少数情况下,我可能想在“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,如果您可以将代码放入订阅中,请改为这样做。