错误时RxJava过滤器

时间:2018-01-12 15:41:06

标签: kotlin rx-java

这个问题与this question松散相关,但没有答案。 Bob Dalgleish的答案很接近,但是不支持来自Single的潜在错误(我认为OP实际上也是如此)。

我基本上正在寻找一种“过滤错误”的方法 - 但是当查找基于RX时,不要认为这存在。我试图获取值列表,通过查找运行它们,并跳过任何返回查找失败的结果(throwable)。我无法弄清楚如何以反应的方式实现这一目标。

我尝试了各种形式的error handling operators与映射相结合。过滤器仅适用于原始值 - 或者至少我无法弄清楚如何使用它来支持我想要做的事情。

在我的用例中,我迭代一个ID列表,从远程服务请求每个ID的数据。如果服务返回404,则该项目不再存在。我应该从本地数据库中删除不存在的项目并继续处理ID。流应该返回查找值列表。

这是一个松散的例子。如何编写getStream()以便canFilterOnError传递?

import io.reactivex.Single
import io.reactivex.schedulers.Schedulers
import org.junit.Test

class SkipExceptionTest {

    private val data: Map<Int, String> = mapOf(
            Pair(1, "one"),
            Pair(2, "two"),
            Pair(4, "four"),
            Pair(5, "five")
    )

    @Test
    fun canFilterOnError() {

        getStream(listOf(1, 2, 3, 4, 5))
                .subscribeOn(Schedulers.trampoline())
                .observeOn(Schedulers.trampoline())
                .test()
                .assertComplete()
                .assertNoErrors()
                .assertValueCount(1)
                .assertValue {
                    it == listOf(
                            "one", "two", "four", "five"
                    )
                }
    }

    fun getStream(list: List<Int>): Single<List<String>> {
        // for each item in the list
        // get it's value via getValue()
        // if a call to getValue() results in a NotFoundException, skip that value and continue
        // mutate the results using mutate()

        TODO("not implemented")
    }

    fun getValue(id: Int): Single<String> {
        return Single.fromCallable {
            val value: String? = data[id]
            if (value != null) {
                data[id]
            } else {
                throw NotFoundException("dat with id $id does not exist")
            }
        }
    }

    class NotFoundException(message: String) : Exception(message)
}

2 个答案:

答案 0 :(得分:3)

我最终将getValue()映射到Optional<String>,然后在其上调用onErrorResumeNext()并返回Single.error()Single.just(Optional.empty())。从那里,主流可以过滤掉空的Optional。

private fun getStream(list: List<Int>): Single<List<String>> {
    return Observable.fromIterable(list)
            .flatMapSingle {
                getValue(it)
                        .map {
                            Optional.of(it)
                        }
                        .onErrorResumeNext {
                            when (it) {
                                is NotFoundException -> Single.just(Optional.empty())
                                else -> Single.error(it)
                            }
                        }
            }
            .filter { it.isPresent }
            .map { it.get() }
            .toList()
}

答案 1 :(得分:2)

首先 .materialize(),然后 .filter()关于非错误事件,然后 .dematerialize()

getStream(/* ... */)
  .materialize()
  .filter(notification -> { return !notification.isOnError(); })
  .dematerialize()