我有此要求::如果调用成功,请对某些服务进行API调用,然后等待WebSocket确认更改,然后关闭加载屏幕。如果呼叫失败-取消加载并显示错误。同样,如果API成功,但我们从未听到WebSocket消息,我们不想让用户一直看着加载屏幕,因此请在5秒钟后将其关闭。 这是我的实现(Kotlin):
var idToConfirm: String = null
val websocket = getWebsocket() //Returns Observable<String>
.filter {
it == idToConfirm
}
.timeout(WEBSOCKET_TIMEOUT_SEC, TimeUnit.SECONDS)
.take(1)
val api = makeApiCall(params) //Returns Single<MyObject>
.flatMapObservable {
idToConfirm = it.id
Observable.just(it)
}
val resultObservable = Observable.combineLatestDelayError(arrayListOf(websocket, api)) {
(it[1] as MyObject).id
}.onErrorResumeNext { t: Throwable ->
if (t is TimeoutException && idToConfirm != null) {
Observable.just(idToConfirm)
} else {
Observable.error(t)
}
}.replay(1).autoConnect() //This shouldn't matter for the question, but in case it does I'm including it
然后,UI订阅resultObservable
。
有效的方法:幸福的道路!当API成功执行并且WebSocket在超时帧内甚至在超时时收到消息时,UI仍将按预期运行。
什么不起作用::如果我们的连接非常差,则WebSocket可能在Retrofit超时之前超时,那么我得到UndeliverableException
。
想法:阅读combineLatestDelayError
上的文档时说:如果任何来源都从不生产物品,而只是终止(正常或有错误),则结果序列立即终止。因此,我认为当WebSocket在发出任何内容之前超时时,它将关闭Observable,因此当API错误超时时,没有订阅者可以将错误传递给该对象。这对于应该等待所有可观察对象终止的方法来说是令人困惑的。我认为我的要求仍然有效,所以有人可以帮我弄清楚如何使其有效吗?