【问题标题】:How to process 400 response in RxJava2如何在 RxJava2 中处理 400 响应
【发布时间】:2018-04-11 10:12:54
【问题描述】:

我正在努力在 RxJava2 中正确处理异常。我正在尝试在OkHttp3 拦截器中刷新我的令牌,如下所示:

tokenRepository.refreshToken(authStateManager.current.refreshToken!!)
                        .doOnError {
                            Log.w(TAG, "Could not obtain new access token.")

                            authStateManager.signOut()
                        }
                        .subscribe { tokenResponse ->
                            Log.d(TAG, "Obtained new access token: " + tokenResponse.toString())

                            authStateManager.updateAfterTokenResponse(TokenResponse.jsonDeserialize(tokenResponse.toString()), null)

                            token = authStateManager.current.accessToken
                        }

如果刷新令牌有效并且请求返回 200,它会很好地工作。但是如果刷新令牌无效并且我收到一些错误代码(例如 400),则执行 doOnError 块,但它会继续执行引发以下异常的订阅块:

retrofit2.adapter.rxjava2.HttpException: HTTP 400 
        at retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:54)
        at retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:37)
...

我尝试使用onErrorReturnonErrorResumeNext,但我想完全跳过订阅块(如果出现错误,只需注销用户,不要尝试做任何事情)。可能吗? refreshToken 方法返回 Single<JsonObject> 类型的响应。

【问题讨论】:

    标签: android kotlin rx-java2


    【解决方案1】:

    您不能在订阅中使用onError 吗?我喜欢为此使用 RxKotlin。例如,我可以执行以下操作:

    .subscribeBy(onSuccess = {
         // do Something in on success
    }, onError = {
         // do something in onError
    })
    

    所以在你的情况下,它可能是这样的:

    tokenRepository.refreshToken(authStateManager.current.refreshToken!!)
        .subscribeBy(onSuccess = {
            Log.d(TAG, "Obtained new access token: " + it.toString())
            authStateManager.updateAfterTokenResponse(TokenResponse.jsonDeserialize(it.toString()), null)
            token = authStateManager.current.accessToken
        }, onError = {
            Log.w(TAG, "Could not obtain new access token.")
            // the variable "it" here is a throwable which means you can determine if it's a RetrofitException and what status code is returned
        })
    

    但是,如果您不想使用 RxKotlin,您可以在 Kotlin 中像这样处理您的 Rx 订阅:

    .subscribe({ Log.d(TAG, "Obtained new access token: " + it.toString()) },
               { Log.e(TAG, "Error is ${it.message}") })
    

    您可以在使用Log.e 的函数的第二部分处理错误。

    【讨论】:

    • 我不确定如何在我的场景中执行此操作。你能在我的用例中解释一下如何修改我的订阅者吗?
    • 是的。首先,将 RxKotlin 依赖项添加到您的 gradle 构建中。然后用 subscribeBy 更改订阅部分。我将在上面修改我的答案。
    • 我很想坚持使用 RxJava...我必须修改我的应用程序的很大一部分,我确信这可以在没有其他依赖项的情况下完成。
    • 是的,如果您将 subscribeBy 替换为 subscribe 就可以(您必须删除 onSuccess 和 onError 词,但原理和结构是相同的。此外,RxKotlin 不是 RxJava 的覆盖 - 它是一个非常小的库,具有一些小功能,使在 Kotlin 中编写 RxJava 代码更具可读性 - 因为归根结底 - RxJava 是为 Java 编写的;而不是 Kotlin
    • @Smajl 我已经添加了一点,除了在 Kotlin 中使用纯 RxJava 的答案的底部
    【解决方案2】:

    我刚刚遇到了同样的问题,但我现在解决了。我不知道我的解释是否正确,但似乎doOnError 没有处理异常。

    您需要使用以onError Consumer 作为参数的subscribe() 方法并在那里处理错误:

    subscribe(Consumer<? super T> onSuccess, Consumer<? super Throwable> onError)
    

    在 Java 中它看起来像这样:

    .subscribe(tokenResponse -> {
                    Log.d(TAG, "Obtained new access token: " + tokenResponse.toString());
                    authStateManager.updateAfterTokenResponse(TokenResponse.jsonDeserialize(tokenResponse.toString()), null);
                    token = authStateManager.current.accessToken;
                }, throwable -> {
                    Log.w(TAG, "Could not obtain new access token.");
                    authStateManager.signOut();
                }));
    

    【讨论】:

      猜你喜欢
      • 2020-10-28
      • 1970-01-01
      • 2020-04-26
      • 2017-02-08
      • 2018-09-11
      • 2017-10-27
      • 1970-01-01
      • 1970-01-01
      • 2017-03-10
      相关资源
      最近更新 更多