RxJava2可能是单个NoSuchElementException

时间:2018-08-28 04:30:43

标签: android rx-java2

我是RxJava2的新手。

我有下一个代码:

fun signIn(): Completable = getCredentials() // get saved token
        .onErrorResumeNext { makeLockSignInRequest() } // if token not saved then get it
        .flatMap { refreshToken(it) } // refresh token
        .doOnSuccess { credentialsManager.saveCredentials(it) } // save updated token
        .doFinally { lock?.onDestroy(context) }!!
        .toCompletable()

private fun getCredentials() = Single.create(SingleOnSubscribe<Credentials> {
    credentialsManager.getCredentials(object : BaseCallback<Credentials, CredentialsManagerException> {
        override fun onSuccess(payload: Credentials?) = it.onSuccess(payload!!)
        override fun onFailure(error: CredentialsManagerException?) = it.onError(error!!)
    })
})

private fun makeLockSignInRequest() = Single.create(SingleOnSubscribe<Credentials> {
    lock = Lock.newBuilder(auth0, object : AuthenticationCallback() {
        override fun onAuthentication(credentials: Credentials?) = it.onSuccess(credentials!!)
        override fun onCanceled() { }
        override fun onError(error: LockException?) = it.onError(error!!)
    })
            .withScheme("demo")
            .withScope("email openid offline_access")
            .withAudience(ApiServiceProvider.DOMAIN + "/api/")
            .closable(true)
            .build(context)

    context.startActivity(lock!!.newIntent(context))
})

private fun refreshToken(storedCredentials: Credentials) = Single.create(SingleOnSubscribe<Credentials> {
    apiClient.renewAuth(storedCredentials.refreshToken!!)
            .addParameter("scope", "openid email offline_access")
            .start(object : BaseCallback<Credentials, AuthenticationException> {
                override fun onSuccess(receivedCredentials: Credentials?) {
                    val newCredentials = Credentials(receivedCredentials!!.idToken, receivedCredentials.accessToken, receivedCredentials.type, storedCredentials.refreshToken, receivedCredentials.expiresAt, receivedCredentials.scope)
                    it.onSuccess(newCredentials)
                }

                override fun onFailure(error: AuthenticationException?) {
                    it.onError(Exception("Error refresh token: ${error!!.description!!}"))
                }
            })
})

此代码将保存令牌并刷新。 同样,如果用户刚刚登录,则刷新令牌。

我想添加过滤器,如下所示:

fun signIn(): Completable = getCredentials()
        .onErrorResumeNext { makeLockSignInRequest() }
        .filter { OffsetDateTime.now(ZoneOffset.UTC).toEpochSecond() > it.expiresAt!!.time } // if token alive then do nothing
        .flatMapSingle { refreshToken(it) }
        .doOnSuccess { credentialsManager.saveCredentials(it) }
        .doFinally { lock?.onDestroy(context) }!!
        .toCompletable()

此代码将因错误而失败:NoSuchElementException 那么如何过滤令牌?

1 个答案:

答案 0 :(得分:2)

.filter将您的Single更改为Maybe。如果在使用Maybe进行转换后,flatMapSingle中没有任何项目(因为不满足过滤器要求),您的代码将返回错误,并带有NoSuchElementException异常。

我要用的是:

fun signIn(): Completable = getCredentials()
    .onErrorResumeNext { makeLockSignInRequest() }
    .filter { OffsetDateTime.now(ZoneOffset.UTC).toEpochSecond() > it.expiresAt!!.time } // if token alive then do nothing
    .flatMapCompletable { refreshToken(it).doAfterSuccess{credentialsManager.saveCredentials(it)}.toCompletable() }
    .doFinally { lock?.onDestroy(context) }!!