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

如何在Interactor中组合Local/Remote的AnyPublisher?解决flatMap报错

问题与解决

我正在编写一个Interactor文件,需要实现优先从本地存储获取数据、本地无数据则从远程存储获取的逻辑。数据流向如下:

ViewModel(GetCode()) >> Interactor(GetCode()-> AnyPublisher<String, Error>) >> Local/Remote Storage -> AnyPublisher<String?, Error>)

LocalDataSourceProvider提供的方法:

func fetchCode(id: String) -> AnyPublisher<String?, Error>

若本地返回nil,则调用RemoteDataSourceProvider的方法:

func fetchCode(id: String) -> AnyPublisher<String, Error>

按照建议修改代码后:

local.fetchCode(voucherId).flatMap {
    if let code = $0 {
        return Just(code).eraseToAnyPublisher()
    }
    return remote.fetchCode(Id: Id).eraseToAnyPublisher()
}

出现报错,翻译为:

没有匹配的'flatMap'候选函数能生成预期的上下文结果类型'AnyPublisher<String?, Error>'

问题原因

报错核心是flatMap闭包返回的Publisher类型不统一:

  • 本地分支返回的Just(code)是AnyPublisher<String, Never>类型,错误类型为Never,且输出是可选性不匹配的非可选String
  • 远程分支返回的是AnyPublisher<String, Error>,输出同样是非可选String
  • 外层预期的结果类型是AnyPublisher<String?, Error>,三者类型完全不匹配,导致编译器无法找到合适的flatMap重载

修复后的代码

local.fetchCode(id: voucherId)
    .flatMap { localCode -> AnyPublisher<String?, Error> in
        if let code = localCode {
            // 将非可选String转为可选,同时设置错误类型为Error,统一分支类型
            return Just(code as String?)
                .setFailureType(to: Error.self)
                .eraseToAnyPublisher()
        } else {
            // 将远程返回的非可选String转为可选,对齐输出类型
            return remote.fetchCode(id: voucherId)
                .map { $0 as String? }
                .eraseToAnyPublisher()
        }
    }

关键调整点

  1. 统一输出类型:把本地和远程的输出都转为String?,匹配外层预期的泛型参数
  2. 统一错误类型:给Just添加setFailureType(to: Error.self),确保错误类型和远程分支一致
  3. 明确闭包返回类型:显式指定闭包返回AnyPublisher<String?, Error>,帮助编译器准确推导

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 08:01:44