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

如何在Combine链式调用中保留并复用上游Publisher的输出?

Combine链式调用中保留上游输出并组合结果的简洁实现

问题描述

需要通过Combine链式调用,结合loadSquad()输出的JSON和processPilots(squad:)输出的[JSON],构建UpdatedPilotsInfo结构体。当前伪代码中无法在flatMap(processPilots)后继续访问上游的squad值,希望找到更简洁的链式实现方式。

结构体定义与理想伪代码:

struct UpdatedPilotsInfo {
    let pilots: [JSON]
    let squad: JSON
}

func buildInfoIdeal() {
    func processPilots(squad: JSON) -> AnyPublisher<[JSON] , XWSImportError> { ... }
    func loadSquad() -> AnyPublisher<JSON, XWSImportError> { ... }
    
    let squadInfoPublisher: AnyPublisher<(JSON, [JSON]), XWSImportError> = JSONSection
        .SquadService_XWSImport_New
        .SquadService
        .loadSquad() // AnyPublisher<JSON, XWSImportError>
        .flatMap(processPilots) // AnyPublisher<[JSON], XWSImportError>
        .???    // 此处需要保留上游squad并与pilots组合
        .map{ tuple -> UpdatedPilotsInfo in
            return UpdatedPilotsInfo(squad: tuple.0, pilots: tuple.1)
        }.eraseToAnyPublisher()
}

当前实现方式

通过拆分两个Publisher再使用Publishers.Zip组合结果:

func buildInfo() -> AnyPublisher<UpdatedPilotsInfo, XWSImportError> {
    func processPilots(squad: JSON) -> AnyPublisher<[JSON] , XWSImportError> { ... }
    func loadSquad() -> AnyPublisher<JSON, XWSImportError> { ... }
    
    let squadPublisher: AnyPublisher<JSON, XWSImportError> = JSONSection
        .SquadService_XWSImport_New
        .SquadService
        .loadSquad()
        .eraseToAnyPublisher()

    let updatedPilots: AnyPublisher<[JSON], XWSImportError> = squadPublisher
        .flatMap{ [weak self] squad -> AnyPublisher<[JSON], XWSImportError> in
            guard let self = self else {
                return Fail(error: XWSImportError.selfDeallocated).eraseToAnyPublisher()
            }
            return self.processPilots(squad: squad)
        }
        .eraseToAnyPublisher()

    let zip = Publishers.Zip(squadPublisher, updatedPilots)
        .eraseToAnyPublisher()

    return zip.map{ tuple -> UpdatedPilotsInfo in 
        return UpdatedPilotsInfo(squad: tuple.0, pilots: tuple.1)
    }.eraseToAnyPublisher() 
}

简洁链式实现方案

无需自定义Operator,利用Combine原生的flatMap与map组合即可实现:

func buildInfo() -> AnyPublisher<UpdatedPilotsInfo, XWSImportError> {
    func processPilots(squad: JSON) -> AnyPublisher<[JSON] , XWSImportError> { ... }
    func loadSquad() -> AnyPublisher<JSON, XWSImportError> { ... }
    
    return JSONSection
        .SquadService_XWSImport_New
        .SquadService
        .loadSquad()
        .flatMap { [weak self] squad in
            guard let self = self else {
                return Fail(error: XWSImportError.selfDeallocated).eraseToAnyPublisher()
            }
            // 在flatMap内部,将processPilots的结果与上游squad组合成元组
            return self.processPilots(squad: squad)
                .map { pilots in (squad, pilots) }
        }
        // 直接用元组构建目标结构体
        .map { UpdatedPilotsInfo(squad: $0.0, pilots: $0.1) }
        .eraseToAnyPublisher()
}

方案说明

  • 在flatMap闭包中,先捕获上游的squad值,调用processPilots获取飞行员数据的Publisher
  • 通过map将squad与飞行员数据包装成元组,让flatMap输出包含两者的Publisher
  • 后续直接通过map将元组转换为UpdatedPilotsInfo,全程保持链式调用,无需拆分多个中间Publisher

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 22:47:48