Observable interval发生错误时如何保持轮询不中断
问题原因
你当前实现的轮询会在请求失败后终止,核心是两个RxJava流生命周期的规则没匹配对:
- 整个响应式流只要接收到
onError事件,在执行完错误兜底逻辑后就会直接终止序列。你把onErrorReturn放在flatMap的下游,单次请求的错误会直接传导到外层的interval轮询主流,onErrorReturn发射完你定义的MyState.Polling兜底值后,会立刻调用onComplete结束整个流,轮询自然就停了。 - 单次API请求属于
flatMap内部的子流,子流的异常不应该泄露到外层轮询主流,否则必然打断主流的定时执行逻辑。
修复实现
把错误处理逻辑下沉到flatMap内部的单个请求子流中,错误发生时直接吞掉异常、不向下游发射任何事件,从根源上避免错误触碰外层轮询流:
private fun pollFromApi(): Observable<MyState> { return Observable.interval(3L, TimeUnit.SECONDS, schedulerProvider.io()) .startWith(0L) .flatMap { api.getState() .toObservable() .map { // 响应映射为MyState的逻辑放在子流内部 // map response to MyState } // 关键:错误处理只作用于当前单次请求 .onErrorResumeNext { // 直接返回空Observable,不发射任何事件,也不会中断外层轮询 Observable.empty() } } .takeUntil { // 终止逻辑保持不变,仅当正常返回的状态命中条件时才停止轮询 // stop polling if certain State is reached } }
逻辑说明
- 单次请求失败只会终止当前这一次的子流,外层
interval的定时逻辑完全不受影响,3秒间隔到了会自动发起下一次请求 - 错误发生时返回
Observable.empty()不会向下游发射任何事件,完全匹配你“忽略错误、不向观察者推送错误相关事件”的需求 - 只有请求正常返回、且映射后的状态命中
takeUntil的终止条件时,整个轮询流才会正常结束 - 如果后续需要在请求失败时发射
MyState.Polling状态做UI提示,只需要把onErrorResumeNext中的Observable.empty()替换为Observable.just(MyState.Polling)即可,不会中断轮询流程
内容的提问来源于stack exchange,提问作者Mehdi Satei
相关产品推荐
相关产品推荐

