如何使用RxSwift实现每10秒发起网络请求并绑定数据到UITableView
实现RxSwift 10秒自动刷新列表的方案
你之前运行失败的核心原因大概率是两点:一是网络请求没有处理异常分支的事件发送,导致序列卡住;二是没有捕获单个请求的错误,一次失败就直接终止了整个定时序列。按照下方步骤调整代码即可实现需求:
1. 修正MarketService的异常事件处理
你当前的fetchMarkets方法中,状态码异常、返回数据为空的分支没有给观察者发送任何事件,会导致序列永久卡住,同时单次请求结束后需要主动发送完成事件避免内存泄漏,修正后代码如下:
class MarketService: MarketServiceProtocol { // 自定义请求错误类型,方便上层识别异常场景 enum RequestError: Error { case invalidStatusCode case emptyData } func fetchMarkets() -> Observable <[Market]> { return Observable.create { observer -> Disposable in RestManager.shared.makeRequest(withEndPoint: "market/v2/get-summary?region=US" , withHttpMethod: .get) { result in if let error = result.error { observer.onError(error) return } guard let response = result.response, 200 ... 299 ~= response.httpStatusCode else { observer.onError(RequestError.invalidStatusCode) return } guard let data = result.data else { observer.onError(RequestError.emptyData) return } do { let decodedData = try JSONDecoder().decode(MarketResult.self, from: data) observer.onNext(decodedData.marketSummaryAndSparkResponse.markets) // 单次请求完成后发送结束事件 observer.onCompleted() } catch { observer.onError(error) } } return Disposables.create { } } } }
2. 改造ViewModel的fetchMarketViewModels方法
需要把定时序列和网络请求绑定,同时做错误隔离避免单次请求失败中断整个定时逻辑,示例代码如下:
func fetchMarketViewModels() -> Observable<[MarketCellViewModel]> { // timer的第一个参数设置为0,代表进入页面立刻发起第一次请求,不需要等10秒 return Observable<Int>.timer(.seconds(0), period: .seconds(10), scheduler: MainScheduler.instance) .flatMapLatest { _ in return self.marketService.fetchMarkets() // 捕获单次请求的错误,不让它中断整个定时序列 .catch { error in print("接口请求失败:\(error.localizedDescription)") // 错误时可根据业务需求返回空数组,或者返回本地缓存的旧数据 return Observable.just([]) } } // 把网络返回的[Market]转换成你需要的CellViewModel数组 .map { markets in markets.map { MarketCellViewModel(market: $0) } } }
- 这里用
flatMapLatest而不是flatMap,如果上一次请求还没返回就触发了下一次定时,会自动取消上一次未完成的请求,避免旧数据覆盖新数据。 - 如果你不需要进入页面立刻加载第一次数据,只需要每隔10秒触发请求,可以把
timer替换为Observable<Int>.interval(.seconds(10), scheduler: MainScheduler.instance)。
3. ViewController绑定逻辑无需修改
你原有的UITableView绑定代码可以直接复用,不需要调整。
其他可选优化项:
- 如果需要支持下拉刷新等手动刷新操作,可以把定时序列和手动刷新的Subject用
merge合并,就能同时支持两种刷新逻辑 - 如果需要页面退到后台暂停定时、回到前台恢复,可以监听App生命周期通知,进入后台时销毁当前序列,回到前台时重新绑定即可
内容的提问来源于stack exchange,提问作者Mat
相关产品推荐
相关产品推荐

