使用 Swift 和 Combine 链接 + 压缩多个网络请求

Chaining + zipping multiple network requests using Swift and Combine

总体用例是 4 个网络请求

C 之后的最终输出应该是 AnyPublisher 类型

我正在尝试使用 Combine 来实现上述目标,到目前为止,我能够使用 Publishers.Zip 执行 A,使用 flatMap 执行 C。我正在努力解决的问题是 B。我可以使用嵌套完成处理程序来做到这一点,但不能使用 flatMap

这是带有字符串的示例代码(不是实际代码)

func overallFunc(arg1: "arg1", arg2: "arg2", arg3: "arg3", arg4: "arg4" ) -> AnyPublisher<String?, Error> {
let pub1 = func1(arg1: arg1, arg2: arg2)
let pub2 = func2(arg1: arg3, arg2: arg4)

let combinedPub = Publishers.Zip(pub1, pub2)

combinedPub
   .flatMap {(response1, response2) in
     return func3(arg1: response1.attribute1, arg2: response2.attribute2)
   }
}

func1func2func3 所有 return URLSession.shared.dataTaskPublisher 和 return 类型说 AnyPublisher<String?, Error>

现在我正在努力完成 overallFunc 的代码。编译器在 flatMap.

附近给出以下错误

Type of expression is ambiguous without more context

如果我在 overallFunc 的最后一行添加一个额外的 return 然后错误变为 No 'flatMap' candidates produce the expected contextual result type 'AnyPublisher<String?, Error>'

简而言之,我想对 Publishers.Zip 和 return 另一个发布者的结果使用 flatMap,这样我就可以添加另一个 flatMap 来执行第 4 个请求,但是我无法弄清楚正确的语法和顺序。

flatMap 的结果将是 String?(请求 3 的结果),然后您希望将其传递给 mapmap 会将 String 转换为第四个请求。然后,您可以将订阅者添加到第四个请求,这将是您整个序列的结果。所以...

pub1
  .zip(pub2)
  .flatMap { (response1, response2) in
     func3(arg1: response1.attribute1, arg2: response2.attribute2)
  }
  .map {
     (func3Result : String?) in
      /* return publisher of 4th request */
  }
  .eraseToAnyPublisher()

所有这一切的结果将是第 4 个请求的发布者。

我认为您混淆代码的尝试已经消除了您遇到的问题。以下代码编译得很好:

func func1(arg1: String, arg2: String) -> AnyPublisher<String?, Error> { fatalError() }
func func2(arg1: String, arg2: String) -> AnyPublisher<String?, Error> { fatalError() }
func func3(arg1: String, arg2: String) -> AnyPublisher<String?, Error> { fatalError() }
func func4(arg1: String) -> AnyPublisher<String?, Error> { fatalError() }

func overallFunc(arg1: String, arg2: String, arg3: String, arg4: String) -> AnyPublisher<String?, Error> {
    Publishers.Zip(
        func1(arg1: arg1, arg2: arg2),
        func2(arg1: arg3, arg2: arg4)
    )
        .flatMap { (response1, response2) in
            func3(arg1: response1 ?? "", arg2: response2 ?? "")
        }
        .flatMap { response3 in
            func4(arg1: response3 ?? "")
        }
        .eraseToAnyPublisher()
}