使用 Swift 和 Combine 链接 + 压缩多个网络请求
Chaining + zipping multiple network requests using Swift and Combine
总体用例是 4 个网络请求
- 一个。请求 1 和 2 需要并行并等待两者
完成
- 乙。请求 3 在 1 和 2 完成后发生
- C。请求 4
3 完成后发生
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)
}
}
func1
、func2
和 func3
所有 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 的结果),然后您希望将其传递给 map
。 map
会将 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()
}
总体用例是 4 个网络请求
- 一个。请求 1 和 2 需要并行并等待两者 完成
- 乙。请求 3 在 1 和 2 完成后发生
- C。请求 4 3 完成后发生
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)
}
}
func1
、func2
和 func3
所有 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 的结果),然后您希望将其传递给 map
。 map
会将 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()
}