You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 05:30:49