首页 > 解决方案 > 如果第二个发布者取决于第一个发布者收到的值,如何压缩两个发布者?

问题描述

我需要创建模型的数据是拆分的,只能通过两个 API 请求接收。

第一个 ( query.snapshotPublisher()) 发布者将获得模型的主要部分(包括它的 ID),第二个请求 ( getPersonalLikeCount(blogModel: blogModel, userID: "408VYXScmxUtUQB91EoTf0LEMgj2")) 将获得一些额外的数据并需要 ID(这是模型的一部分,这就是我传递完整模型的原因)我从第一个请求中得到的。

如果两个请求都是独立的,我将使用.Zip(other: )运算符,但由于第二个请求依赖于第一个请求,我尝试了以下操作以将模型传递给第二个发布者。

但是通过这种方法,第二个发布者在发送第一个值后会被取消,因此即使getPersonalLikeCount发布者获取新数据并应该再次发布它们也不会更新模型。

private func getBlogs(from query: Query) -> AnyPublisher<BlogModel, Error> {
    let publisher = query.snapshotPublisher()
        .flatMap { [self] blogModel -> AnyPublisher<(BlogModel, Int), Never> in
            let blogModelPublisher = Just(blogModel)
            let likeCountPublisher = getPersonalLikeCount(blogModel: blogModel, userID: "408VYXScmxUtUQB91EoTf0LEMgj2")
            let combined = Combine.Publishers.Zip(blogModelPublisher, likeCountPublisher)
            return combined.eraseToAnyPublisher()
        }
        .map { blogModel, personalLikeCount -> BlogModel in
            var newModel = blogModel
            newModel.personalLikeCount = personalLikeCount
            return newModel
        }
        .eraseToAnyPublisher()
    return publisher
}

标签: swiftcombine

解决方案


语义上,如果您想用您使用的新请求重新启动一个请求,map然后是switchToLatest. 当且仅当您想并行执行操作时,您才使用flatMap. 奇怪的是,Combine 没有 concatMap,您可以在其他反应式框架中使用它来连续执行操作。在你的情况下

  1. 提出第一个请求
  2. 映射到第二个请求
  3. 将两个值映射到一个元组中
  4. 切换到最新
  5. 将元组映射到您的结果中
doTheFirstThingPublisher
 .map { firstValue in 
   doTheSecondThingPubisher(with: firstValue)
     .map { secondValue in (firstValue, secondValue) }
 }
 .switchToLatest()
 .map { firstValue, secondValue in
   makeFinalValue(from: firstValue, and: secondValue)
  }

推荐阅读