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

最佳实践:Combine框架流存在多种Error类型时的错误处理方案

Combine 框架下 Repository 层错误类型设计最佳实践

你当前使用的MVVM架构分层如下:
MVVM架构分层图

针对错误类型设计的问题没有绝对最优解,完全取决于上层消费方对错误的处理粒度需求,你可以从以下几个维度判断选型:


核心考量维度

  • 上层错误处理的粒度:如果你的ViewModel/View层只需要区分「网络错误」「本地缓存错误」「权限错误」这类通用分类,不需要感知methodX还是methodY特有的错误,选统一大错误类型即可;如果不同业务方法的错误需要做完全不同的交互(比如methodX抛错要弹出引导去开权限,methodY抛错只需要toast提示),选单方法专属小错误类型更清晰。
  • 项目迭代维护成本:如果是中小型项目、Repository方法总数不超过20个,统一大错误类型维护更简单,所有mapError逻辑统一收敛,不需要每个方法单独定义枚举;如果是大型多模块项目、不同业务线的Repository方法逻辑完全独立,单方法专属错误类型可以避免无关错误枚举值互相干扰,编译期就能保证上层不会处理到当前方法根本不会抛出的错误。
  • 错误埋点/上报需求:如果需要统一收集所有Repository层的错误做埋点,统一大错误类型更方便做统一的日志上报逻辑,不需要对每个方法的错误单独做类型判断。

两种方案的具体实现

方案1:统一Repository错误类型(适用90%常规业务场景)

定义一个涵盖所有数据源可能抛出的错误枚举,同时预留通用错误case兜底:

enum RepositoryError: Error {
    case sourceAError(ErrorA)
    case sourceBError(ErrorB)
    case sourceCError(ErrorC)
    case sourceDError(ErrorD)
    case unknown(Error) // 兜底未定义的错误类型
}

Combine中使用示例:

func methodX() -> AnyPublisher<DataTypeX, RepositoryError> {
    sourceA.fetch()
        .catch { _ in sourceB.fetch() }
        .catch { _ in sourceC.fetch() }
        .mapError { error in
            // 把各个数据源的错误映射为统一枚举
            switch error {
            case let errorA as ErrorA:
                return .sourceAError(errorA)
            case let errorB as ErrorB:
                return .sourceBError(errorB)
            case let errorC as ErrorC:
                return .sourceCError(errorC)
            default:
                return .unknown(error)
            }
        }
        .eraseToAnyPublisher()
}

方案2:单方法专属错误类型(适用强类型要求的大型项目)

为每个方法单独定义错误枚举,只包含当前方法可能抛出的错误,编译期就能保证错误处理的完整性:

// methodX专属错误
enum MethodXError: Error {
    case sourceAError(ErrorA)
    case sourceBError(ErrorB)
    case sourceCError(ErrorC)
}

// methodY专属错误
enum MethodYError: Error {
    case sourceAError(ErrorA)
    case sourceDError(ErrorD)
    case sourceCError(ErrorC)
}

这种方案的优势是上层在处理错误时不会出现无效的case判断,比如处理methodX的错误时不需要考虑sourceD相关的错误,编译器还能提示你是否漏了枚举case处理。


折中推荐方案

如果不想写太多重复的枚举定义,可以把通用的错误case抽成公共的,再用关联枚举或者Error协议来做扩展,既保证复用性也不会出现多余的错误类型。

内容的提问来源于stack exchange,提问作者Ahmed Shendy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 11:48:03