Android RxJava2 - 如何在抛出错误时进行 api 调用?
Android RxJava2 - How to make api call when error is thrown?
所以我目前正在使用 flatMap 将 API 调用链接在一起,它在我的用例中运行良好。如果我的其中一个调用 return 是一个失败的响应代码,那么我将传递一个错误单,其中包含一个可抛出的消息,其中包含一条消息,说明哪个调用失败并继续进行。这是我现在的做法:
dataManager.apiCall1(dataManager.sessionId!!)
.subscribeOn(schedulerProvider.io())
.observeOn(schedulerProvider.ui())
.flatMap{apiCall1Response ->
if (apiCall1Response.isSuccessful && apiCall1Response.body() != null) {
// First api call was successful, execute api call 2.
return@flatMap dataManager.apiCall2(apiCall1Response.importantVal)
} else {
// First api call failed
return@flatMap Single.error<Throwable>(Throwable("First api call failed."))
}
}.flatMap{apiCall2Response ->
if (apiCall2Response != null && apiCall2Response.isSuccessful && apiCall2Response.body() != null) {
// Second api call was successful, execute api call 3.
return@flatMap dataManager.apiCall3(apiCall2Response.importantVal)
} else if (apiCall2Response is Throwable) {
// Api Call 1 Failed.
return@flatMap Single.error<Throwable>(apiCall2Response)
} else {
// Second api call failed
return@flatMap Single.error<Throwable>(Throwable("Second api call failed."))
}
}.subscribe({apiCall3Response ->
if (apiCall3Response is Response<*> && apiCall3Response.body() != null) {
// Success!
navigator?.successful(response)
} else if (apiCall3Response is Throwable) {
// Something failed from before.
navigator?.handleError(apiCall3Response)
} else {
// Third api call failed, handle error
navigator!!.handleError(Throwable("Api call 3 failed."))
}
}, {throwable ->
navigator!!.handleError(throwable)
})
好吧,现在我意识到,如果我的第一个 api 调用成功而我的任何其他调用都失败了,我需要进行另一个 api 调用。这是登录用户的一系列调用,如果登录调用成功,但下一次调用失败,我们将需要调用 api 注销端点。我知道在 subscribe() 方法中创建另一个单例是不好的做法,所以我不想那样做。我宁愿通过注销调用,但问题是无法知道哪个 api 调用在订阅方法中被 returned,因为注销和 apiCall3 return 空尸体。如果 apiCall3 失败,我还想调用注销端点,但不确定这是否可能。这是我正在尝试做的事情:
dataManager.apiCall1(dataManager.sessionId!!)
.subscribeOn(schedulerProvider.io())
.observeOn(schedulerProvider.ui())
.flatMap{apiCall1Response ->
if (apiCall1Response.isSuccessful && apiCall1Response.body() != null) {
// First api call was successful, execute api call 2.
return@flatMap dataManager.apiCall2(apiCall1Response.importantVal)
} else {
// First api call failed
return@flatMap Single.error<Throwable>(Throwable("First api call failed."))
}
}.flatMap{apiCall2Response ->
if (apiCall2Response != null && apiCall2Response.isSuccessful && apiCall2Response.body() != null) {
// Second api call was successful, execute api call 3.
return@flatMap dataManager.apiCall3(apiCall2Response.importantVal)
} else if (apiCall2Response is Throwable) {
// Api Call 1 Failed.
return@flatMap Single.error<Throwable>(apiCall2Response)
} else {
// Second api call failed, logout
return@flatMap dataManager.logoutApiCall()
}
}.subscribe({apiCall3OrLogoutResponse ->
// I would like to be able to determine which call this response is from. That is the question.
if (apiCall3OrLogoutResponse is Response<*> && apiCall3OrLogoutResponse.body() != null) {
// Success!
navigator?.successful(response)
} else if (apiCall3OrLogoutResponse is Throwable) {
// Something failed from before.
navigator?.handleError(apiCall3OrLogoutResponse)
} else {
// Third api call or logout call failed, handle error
if (apiCall3OrLogoutResponse is ApiCall3) {
// Api Call 3 failed.
// Somehow call logout api endpoint
} else if (apiCall3OrLogoutResponse is LogoutCall {
// Logout call failed.
navigator?.handleError(Throwable("Logout failed."))
}
}
}, {throwable ->
navigator!!.handleError(throwable)
})
有更好的方法吗?我的用例是进行三个连续的 api 调用,如果第一个失败,则向订阅者发送一个可抛出的对象,如果第一个成功并且之后失败,则进行另一个 api 调用。
我通过抛出自定义异常而不是向下传递 Single.error 并在 flatMapCompletable 而不是订阅中检查我的最终调用来解决这个问题。然后,如果异常不是登录异常,我会在 doOnError 中调用注销端点。
dataManager.apiCall1(dataManager.sessionId!!)
.subscribeOn(schedulerProvider.io())
.observeOn(schedulerProvider.ui())
.flatMap{apiCall1Response ->
if (apiCall1Response.isSuccessful && apiCall1Response.body() != null) {
// First api call was successful, execute api call 2.
return@flatMap dataManager.apiCall2(apiCall1Response.importantVal)
} else {
// First api call failed
throw ApiCall1Exception("Api Call 1 failed.")
}
}.flatMap{apiCall2Response ->
if (apiCall2Response != null && apiCall2Response.isSuccessful && apiCall2Response.body() != null) {
// Second api call was successful, execute api call 3.
return@flatMap dataManager.apiCall3(apiCall2Response.importantVal)
} else {
// Second api call failed
throw Throwable("Api call 2 failed.")
}
}.flatMapCompletable{apiCall3Response ->
if (apiCall3Response.body() != null) {
// All api calls were successful!
Completable.complete()
} else {
// Third api call failed.
throw Throwable("Api call 3 failed.")
}
}.doOnError{throwable ->
if (throwable !is ApiCall1Exception) {
// Api call 1 was successful, but something else failed, call logout endpoint.
dataManager.logout()
.subscribeOn(schedulerProvider.io())
.observeOn(schedulerProvider.ui())
}
}.subscribe({
// Success!
navigator?.success()
}, {throwable ->
// Something failed!
navigator?.handleError(throwable)
})
所以我目前正在使用 flatMap 将 API 调用链接在一起,它在我的用例中运行良好。如果我的其中一个调用 return 是一个失败的响应代码,那么我将传递一个错误单,其中包含一个可抛出的消息,其中包含一条消息,说明哪个调用失败并继续进行。这是我现在的做法:
dataManager.apiCall1(dataManager.sessionId!!)
.subscribeOn(schedulerProvider.io())
.observeOn(schedulerProvider.ui())
.flatMap{apiCall1Response ->
if (apiCall1Response.isSuccessful && apiCall1Response.body() != null) {
// First api call was successful, execute api call 2.
return@flatMap dataManager.apiCall2(apiCall1Response.importantVal)
} else {
// First api call failed
return@flatMap Single.error<Throwable>(Throwable("First api call failed."))
}
}.flatMap{apiCall2Response ->
if (apiCall2Response != null && apiCall2Response.isSuccessful && apiCall2Response.body() != null) {
// Second api call was successful, execute api call 3.
return@flatMap dataManager.apiCall3(apiCall2Response.importantVal)
} else if (apiCall2Response is Throwable) {
// Api Call 1 Failed.
return@flatMap Single.error<Throwable>(apiCall2Response)
} else {
// Second api call failed
return@flatMap Single.error<Throwable>(Throwable("Second api call failed."))
}
}.subscribe({apiCall3Response ->
if (apiCall3Response is Response<*> && apiCall3Response.body() != null) {
// Success!
navigator?.successful(response)
} else if (apiCall3Response is Throwable) {
// Something failed from before.
navigator?.handleError(apiCall3Response)
} else {
// Third api call failed, handle error
navigator!!.handleError(Throwable("Api call 3 failed."))
}
}, {throwable ->
navigator!!.handleError(throwable)
})
好吧,现在我意识到,如果我的第一个 api 调用成功而我的任何其他调用都失败了,我需要进行另一个 api 调用。这是登录用户的一系列调用,如果登录调用成功,但下一次调用失败,我们将需要调用 api 注销端点。我知道在 subscribe() 方法中创建另一个单例是不好的做法,所以我不想那样做。我宁愿通过注销调用,但问题是无法知道哪个 api 调用在订阅方法中被 returned,因为注销和 apiCall3 return 空尸体。如果 apiCall3 失败,我还想调用注销端点,但不确定这是否可能。这是我正在尝试做的事情:
dataManager.apiCall1(dataManager.sessionId!!)
.subscribeOn(schedulerProvider.io())
.observeOn(schedulerProvider.ui())
.flatMap{apiCall1Response ->
if (apiCall1Response.isSuccessful && apiCall1Response.body() != null) {
// First api call was successful, execute api call 2.
return@flatMap dataManager.apiCall2(apiCall1Response.importantVal)
} else {
// First api call failed
return@flatMap Single.error<Throwable>(Throwable("First api call failed."))
}
}.flatMap{apiCall2Response ->
if (apiCall2Response != null && apiCall2Response.isSuccessful && apiCall2Response.body() != null) {
// Second api call was successful, execute api call 3.
return@flatMap dataManager.apiCall3(apiCall2Response.importantVal)
} else if (apiCall2Response is Throwable) {
// Api Call 1 Failed.
return@flatMap Single.error<Throwable>(apiCall2Response)
} else {
// Second api call failed, logout
return@flatMap dataManager.logoutApiCall()
}
}.subscribe({apiCall3OrLogoutResponse ->
// I would like to be able to determine which call this response is from. That is the question.
if (apiCall3OrLogoutResponse is Response<*> && apiCall3OrLogoutResponse.body() != null) {
// Success!
navigator?.successful(response)
} else if (apiCall3OrLogoutResponse is Throwable) {
// Something failed from before.
navigator?.handleError(apiCall3OrLogoutResponse)
} else {
// Third api call or logout call failed, handle error
if (apiCall3OrLogoutResponse is ApiCall3) {
// Api Call 3 failed.
// Somehow call logout api endpoint
} else if (apiCall3OrLogoutResponse is LogoutCall {
// Logout call failed.
navigator?.handleError(Throwable("Logout failed."))
}
}
}, {throwable ->
navigator!!.handleError(throwable)
})
有更好的方法吗?我的用例是进行三个连续的 api 调用,如果第一个失败,则向订阅者发送一个可抛出的对象,如果第一个成功并且之后失败,则进行另一个 api 调用。
我通过抛出自定义异常而不是向下传递 Single.error 并在 flatMapCompletable 而不是订阅中检查我的最终调用来解决这个问题。然后,如果异常不是登录异常,我会在 doOnError 中调用注销端点。
dataManager.apiCall1(dataManager.sessionId!!)
.subscribeOn(schedulerProvider.io())
.observeOn(schedulerProvider.ui())
.flatMap{apiCall1Response ->
if (apiCall1Response.isSuccessful && apiCall1Response.body() != null) {
// First api call was successful, execute api call 2.
return@flatMap dataManager.apiCall2(apiCall1Response.importantVal)
} else {
// First api call failed
throw ApiCall1Exception("Api Call 1 failed.")
}
}.flatMap{apiCall2Response ->
if (apiCall2Response != null && apiCall2Response.isSuccessful && apiCall2Response.body() != null) {
// Second api call was successful, execute api call 3.
return@flatMap dataManager.apiCall3(apiCall2Response.importantVal)
} else {
// Second api call failed
throw Throwable("Api call 2 failed.")
}
}.flatMapCompletable{apiCall3Response ->
if (apiCall3Response.body() != null) {
// All api calls were successful!
Completable.complete()
} else {
// Third api call failed.
throw Throwable("Api call 3 failed.")
}
}.doOnError{throwable ->
if (throwable !is ApiCall1Exception) {
// Api call 1 was successful, but something else failed, call logout endpoint.
dataManager.logout()
.subscribeOn(schedulerProvider.io())
.observeOn(schedulerProvider.ui())
}
}.subscribe({
// Success!
navigator?.success()
}, {throwable ->
// Something failed!
navigator?.handleError(throwable)
})