Swift Combine实现GitHub仓库及分支组合请求问题
解决Combine组合仓库与分支请求的方案
假设你已经有如下基础定义(可根据实际代码调整):
// 仓库模型示例 struct Repo: Decodable { let name: String // 其他仓库属性... } // 分支模型示例 struct Branch: Decodable { let name: String // 其他分支属性... } // 目标模型 struct BranchSectionModel { let repo: Repo let branches: [Branch] } // 已有的两个Publisher函数 func fetchRepos(forOrg orgName: String) -> AnyPublisher<[Repo], Error> { // 你的现有实现... } func fetchBranches(forRepo repoName: String, orgName: String) -> AnyPublisher<[Branch], Error> { // 你的现有实现... }
核心组合逻辑
要将两个请求串联并生成目标数组,关键是用flatMap逐个处理仓库的分支请求,再通过collect()汇总结果:
func fetchOrgRepoBranches(orgName: String) -> AnyPublisher<[BranchSectionModel], Error> { fetchRepos(forOrg: orgName) .flatMap { repos -> AnyPublisher<BranchSectionModel, Error> in // 将仓库数组转为单个仓库的Publisher序列 Publishers.Sequence(sequence: repos) .flatMap { repo -> AnyPublisher<BranchSectionModel, Error> in // 为每个仓库发起分支请求,同时保留仓库对象 fetchBranches(forRepo: repo.name, orgName: orgName) .map { branches in // 组合成目标模型 BranchSectionModel(repo: repo, branches: branches) } .eraseToAnyPublisher() } .eraseToAnyPublisher() } .collect() // 将所有单个SectionModel收集为数组 .eraseToAnyPublisher() }
关键操作符说明
flatMap:第一层flatMap把仓库数组拆成单个仓库的流;第二层flatMap为每个仓库发起分支请求,同时将仓库对象传递到下游,方便组合模型。Publishers.Sequence:把普通数组转成Combine的Publisher序列,实现逐个处理仓库。collect():将上游发出的所有BranchSectionModel单个元素打包成一个数组,最终输出目标类型。
错误处理补充
如果想让单个仓库的分支请求失败不影响整体流程,可以在分支请求处添加容错处理:
// 在第二层flatMap内修改分支请求逻辑 fetchBranches(forRepo: repo.name, orgName: orgName) .catch { _ in // 分支请求失败时返回空分支数组 Just([]) } .map { branches in BranchSectionModel(repo: repo, branches: branches) } .eraseToAnyPublisher()
这样即使某仓库的分支请求出错,依然会生成包含该仓库和空分支的SectionModel,不会导致整个请求中断。
内容的提问来源于stack exchange,提问作者Evgenii Burdiuzha
相关产品推荐
相关产品推荐

