如何在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
相关产品推荐
相关产品推荐

