ios - 在 RxSwift 中解析 JSON 并处理来自 API 的错误响应

标签 ios swift rx-swift

我是 RxSwift 的新手。我有一个 BackendProvider 来处理与我的 API 的通信。我想要一个配置文件同步,以便我可以动态检索一些参数。我有一个后备案例,其中包含一个本地存储的 JSON 文件,如果我的 API 无法访问或我的 JSON 解析失败,我可以访问该文件:

ConfigFileBackendService

open func getLatestConfig() -> Observable<ConfigFile?> {            
        let urlString = IoC.urlProviderService.getConfigFileUrl()?.absoluteString ?? ""
        let configFileJSONData = IoC.backendCommunicationService.getJsonData(url: urlString)

        return configFileJSONData.map { data in
            if let configFile = try? JSONDecoder().decode(ConfigFile.self, from: data) {
                return configFile
            } else {
                return nil
            }
        }
    }

ConfigFileProcessService

这是回退到本地存储文件的那个:

func getConfigFile() -> Observable<ConfigFile> {
        return IoC.configFileBackendService.getLatestConfig()
            .map { configFile in
                guard let configFile = configFile else { fatalError() }
                return configFile
            }
            .catchError { error in
                // Use default config
                let localURL = IoC.urlProviderService.getLocalConfigFileUrl()
                do {
                    let data = try Data(contentsOf: localURL)
                    let configFile = try JSONDecoder().decode(ConfigFile.self, from: data)
                    return Observable.just(configFile)
                } catch {
                    fatalError("Error loading local config")
                }
        }
    }

这种方法有效,但我对 .map/.catchError block 有疑问。有没有更好的方法来处理错误情况?也许我应该先使用 onNext 然后使用 onError?提前致谢!

最佳答案

除了处理错误的多种方法外,您所拥有的看起来不错。在一种情况下你使用 try? 而另一种情况使用 do...catch 并且你的 getJsonData(url:) 可能会发出一个 Observable 错误.你无处不在。我建议您选择一种错误处理系统并坚持使用。最灵活的是 Event.error。所以像这样:

func getLatestConfig() -> Observable<ConfigFile> {
    let urlString = IoC.urlProviderService.getConfigFileUrl()?.absoluteString ?? ""
    let configFileJSONData = IoC.backendCommunicationService.getJsonData(url: urlString)
    return configFileJSONData.map { try JSONDecoder().decode(ConfigFile.self, from: $0) }
}

请注意,我只是让解码错误路由到一个 Observable 错误事件中。无需以这种方式处理 nil

func getConfigFile() -> Observable<ConfigFile> {
    return IoC.configFileBackendService.getLatestConfig()
        .catchError { _ in
            let localURL = IoC.urlProviderService.getLocalConfigFileUrl()
            let data = try! Data(contentsOf: localURL)
            let configFile = try! JSONDecoder().decode(ConfigFile.self, from: data)
            return Observable.just(configFile)
        }
}

如果任何一个尝试都失败了,你就会崩溃,所以只需在它们上面放一个 ! 。它具有相同的效果。您应该考虑将错误 block 放入一个单独的、可测试的函数中,因为不能保证您会在程序的常规运行期间命中它,并且它可能在您没有意识到的情况下被破坏。

最后,对于上面的内容,没有理由在订阅中提供 onError: 处理程序,因为 getConfigFile() observable 永远不会发出错误。您可能希望函数返回一个驱动程序,而不是让事实更明确。

关于ios - 在 RxSwift 中解析 JSON 并处理来自 API 的错误响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53867736/

相关文章:

swift - Rx swift : Observe viewDidLoad from view model without Subjects

ios - 无法创建 IPA 文件

ios - 如何在屏幕底部制作uitableviewcontroller

ios - 使用 YTPlayerView 在 iOS 中播放嵌入式 YouTube 视频失败并出现限制错误

Swift:错误会忽略 try 语句

ios - 将 RxDataSource 添加到 UICollectionView 时 Xcode 崩溃

ios - 在RxSwift单元测试中模拟和验证结果

ios - CBPeripheral writeValue : forDescriptor: 崩溃

ios - 使用消耗品型号 IAP iOS 购买 IAP 后,从多张照片中的精选照片中删除 Logo

iphone - UIScrollView 内部分透明内容的奇怪行为