Swift Combine中flatMap链式调用的错误捕获方案咨询
解决Combine中flatMap捕获错误并执行API请求的问题
当本地存储的fetchVoucherCode抛出错误时,原代码中的flatMap不会触发,错误会直接流向下游。你需要通过catch操作符捕获上游错误,同时保留本地查询无结果时的API请求逻辑,具体实现如下:
修改后的代码
// 先从本地存储(realm)获取 voucherCodeStorageProvider.fetchVoucherCode(voucherId) .flatMap { code -> AnyPublisher<String?, Error> in if let code = code { // 本地查到code,直接返回结果 return Just(code) .setFailureType(to: Error.self) .eraseToAnyPublisher() } else { // 本地无结果,请求API并保存到本地 return self.voucherCodeProvider.fetchVoucherCode(voucherId: voucherId) .handleEvents(receiveOutput: { code in guard let code = code else { return } _ = self.voucherCodeStorageProvider.saveVoucherCode(code, voucherId) }) .mapError { $0 as Error } .eraseToAnyPublisher() } } // 捕获本地存储请求的错误,直接执行API请求逻辑 .catch { _ -> AnyPublisher<String?, Error> in return self.voucherCodeProvider.fetchVoucherCode(voucherId: voucherId) .handleEvents(receiveOutput: { code in guard let code = code else { return } _ = self.voucherCodeStorageProvider.saveVoucherCode(code, voucherId) }) .mapError { $0 as Error } .eraseToAnyPublisher() } .eraseToAnyPublisher()
优化:消除重复代码
上面的API请求逻辑重复,可抽成独立方法简化代码:
private func fetchAndSaveVoucherCode(voucherId: String) -> AnyPublisher<String?, Error> { return voucherCodeProvider.fetchVoucherCode(voucherId: voucherId) .handleEvents(receiveOutput: { code in guard let code = code else { return } _ = self.voucherCodeStorageProvider.saveVoucherCode(code, voucherId) }) .mapError { $0 as Error } .eraseToAnyPublisher() } // 调用代码 voucherCodeStorageProvider.fetchVoucherCode(voucherId) .flatMap { code -> AnyPublisher<String?, Error> in if let code = code { return Just(code) .setFailureType(to: Error.self) .eraseToAnyPublisher() } else { return self.fetchAndSaveVoucherCode(voucherId: voucherId) } } .catch { _ in return self.fetchAndSaveVoucherCode(voucherId: voucherId) } .eraseToAnyPublisher()
核心逻辑说明
catch操作符会捕获上游(本地存储请求)的所有错误,返回你指定的新Publisher(此处为API请求逻辑),实现错误场景下的自动降级。- 抽离重复逻辑到独立方法,既减少冗余代码,也便于后续维护修改。
内容的提问来源于stack exchange,提问作者pankaj
相关产品推荐
相关产品推荐

