如果第二个发布者取决于第一个发布者收到的值,如何压缩两个发布者?

时间:2021-01-19 23:06:47

标签: swift combine

我创建模型所需的数据是拆分的,只能通过两个 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
}

1 个答案:

答案 0 :(得分:0)

从语义上讲,如果您想用一个新请求重新启动一个请求,请使用 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)
  }