簡體   English   中英

捕獲錯誤並在RxJava2中返回新類型

[英]Catch an error and return a new type in RxJava2

我有一個流:

val symbols: Single<List<Symbol>>

現在,我想使用map()將流轉換為UI狀態:

private fun cool(): Single<SymbolContract.State> =
    symbols.map { SymbolContract.State.Symbols(it) }

我想要做的是在單個上游symbols上捕獲一個錯誤,以便可以捕獲任何錯誤,然后返回SymbolContract.State.GeneralError()

我想要類似onErrorMap()東西。 不幸的是,將onErrorResumeItem放在symbols上不起作用,因為它需要返回List<Symbol>

我可以想到一些丑陋的方法,但是最干凈的是什么?

我建議您使用全局處理錯誤。 我給你一個樣本,這樣你就可以理解。 (這是kotlin),您可以捕獲盡可能多的異常,其中一些是我自定義的異常。 請記住,此示例是關於Reactive Webflux的,但是您明白了。 在其他地方也差不多

@Configuration
class ExceptionTranslator {

    @Bean
    @Order(-1)
    fun handle(objectMapper: ObjectMapper): ErrorWebExceptionHandler {
        return ErrorWebExceptionHandler { exchange, ex ->
            if (exchange.response.isCommitted) {
                return@ErrorWebExceptionHandler Mono.error(ex)
            }

            val response = exchange.response
            response.statusCode = HttpStatus.INTERNAL_SERVER_ERROR
            response.headers.contentType = MediaType.APPLICATION_PROBLEM_JSON_UTF8

            val url: String

            var message = ex.message
            var params = mutableMapOf<String, Any>()

            when (ex) {
                is ParametricException -> {
                    url = ex.url
                    params = ex.params
                }
                is BaseException -> {
                    url = ex.url
                }
                is BadCredentialsException -> {
                    url = INVALID_CREDENTIAL_TYPE
                    message = ex.message ?: "Wrong Credentials"
                }
                is ConcurrencyFailureException -> {
                    url = INTERNAL_TYPE
                    message = ERR_CONCURRENCY_FAILURE
                }
                is MethodArgumentNotValidException -> {
                    val result = ex.bindingResult
                    val fieldErrors = result.fieldErrors.map {
                        FieldErrorVM(it.objectName, it.field, it.code ?: "Unknown")
                    }

                    url = CONSTRAINT_VIOLATION_TYPE
                    message = ERR_VALIDATION
                    params = Collections.singletonMap("errors", fieldErrors)
                }
                else -> url = INTERNAL_TYPE
            }

            if (ex is BaseException) {
                response.statusCode = HttpStatus.valueOf(ex.status.code())
            }

            val bytes = objectMapper.writeValueAsBytes(ProblemVM(url, message ?: "Internal Error", params))
            val buffer = response.bufferFactory().wrap(bytes)
            response.writeWith(Mono.just(buffer))
        }
    }

}

找到一個明確的答案:

private fun symbols(): Single<SymbolContract.State> =
       symbols.map<SymbolContract.State> { SymbolContract.State.Symbols(it) }
            .onErrorReturnItem(SymbolContract.State.Error(SymbolContract.State.Error.Type.Network))

onErrorReturnItem必須位於映射之后,並且映射需要顯式類型參數。

暫無
暫無

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

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