如何在 Alamofire 中处理多个网络调用
How to handle multiple network call in Alamofire
我需要在视图控制器中调用 2 个 api 从服务器获取一些数据,我希望它们同时启动,但只有在它们都返回时才会触发下一步(无所谓这是成功还是失败)。
我可以想出 2 个解决方案:
1. 将它们链接在一起。调用api1,在api1的result handler中调用api2,等待api2的结果
2.设置2个Bool指标变量,创建一个检查函数,如果这两个指标都为真,则执行下一步。在两个Api result handler中,设置相应的指标变量,然后调用检查函数来决定是否可以进行
第一个还不够,我不能说第二个是一个优雅的解决方案。 Alamofire 在 Reactivecocoa 中是否有类似组合信号的东西?或者有更好的解决方案吗?
您的评估 100% 正确。目前,您列出的两个选项实际上是唯一可能的方法。我同意你的看法,根据你的用例,你的第二个选择比第一个好得多。
如果你想将 ReactiveCocoa 与 Alamofire 结合起来,那当然是可能的,但据我所知还没有完成。您还可以调查 PromiseKit 是否能够提供一些帮助,但它还没有与 Alamofire 粘合在一起。尝试将这些库中的任何一个与 Alamofire 响应序列化程序结合起来绝非易事。
换个角度,我真的不认为 ReactiveCocoa 或 PromiseKit 非常适合您的用例,因为您没有链接服务调用,而是 运行 并行调用它们。此外,您仍然需要 运行 所有解析逻辑并确定每个解析逻辑是成功还是失败,然后相应地更新您的应用程序。我要说的是,选项 2 将是迄今为止最好的选择,除非你想全力以赴将 PromiseKit 或 ReactiveCocoa 与 Alamofire 的响应序列化程序结合起来。
以下是我建议的让事情不那么复杂的方法。
import Foundation
import Alamofire
class ParallelServiceCaller {
var firstServiceCallComplete = false
var secondServiceCallComplete = false
func startServiceCalls() {
let firstRequest = Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["first": "request"])
firstRequest.responseString { request, response, dataString, error in
self.firstServiceCallComplete = true
self.handleServiceCallCompletion()
}
let secondRequest = Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["second": "request"])
secondRequest.responseString { request, response, dataString, error in
self.secondServiceCallComplete = true
self.handleServiceCallCompletion()
}
}
private func handleServiceCallCompletion() {
if self.firstServiceCallComplete && self.secondServiceCallComplete {
// Handle the fact that you're finished
}
}
}
实施非常简洁,易于遵循。虽然我理解你想要摆脱完成标志和回调函数的愿望,但其他选项,如 ReactiveCocoa and/or PromiseKit 仍然会有额外的逻辑,最终可能会使事情变得更复杂。
另一种可能的选择是使用调度组和信号量,但这确实增加了复杂性,但可以使您更接近 ReactiveCocoa 或 PromiseKit 风格的方法。
我希望这有助于阐明一些问题。
DispatchGroup
是并行处理多个依赖请求的好选择
func loadData() {
let dispatchGroup = DispatchGroup()
func startRequests() {
dispatchGroup.enter()
loadDataRequest1()
dispatchGroup.enter()
loadDataRequest2()
dispatchGroup.notify(queue: .main) { [weak self] in
// Process your responses
}
loadDataRequest1() {
// Save your response
dispatchGroup.leave()
}
loadDataRequest2() {
// Save your response
dispatchGroup.leave()
}
}
startRequests()
}
我需要在视图控制器中调用 2 个 api 从服务器获取一些数据,我希望它们同时启动,但只有在它们都返回时才会触发下一步(无所谓这是成功还是失败)。 我可以想出 2 个解决方案: 1. 将它们链接在一起。调用api1,在api1的result handler中调用api2,等待api2的结果 2.设置2个Bool指标变量,创建一个检查函数,如果这两个指标都为真,则执行下一步。在两个Api result handler中,设置相应的指标变量,然后调用检查函数来决定是否可以进行
第一个还不够,我不能说第二个是一个优雅的解决方案。 Alamofire 在 Reactivecocoa 中是否有类似组合信号的东西?或者有更好的解决方案吗?
您的评估 100% 正确。目前,您列出的两个选项实际上是唯一可能的方法。我同意你的看法,根据你的用例,你的第二个选择比第一个好得多。
如果你想将 ReactiveCocoa 与 Alamofire 结合起来,那当然是可能的,但据我所知还没有完成。您还可以调查 PromiseKit 是否能够提供一些帮助,但它还没有与 Alamofire 粘合在一起。尝试将这些库中的任何一个与 Alamofire 响应序列化程序结合起来绝非易事。
换个角度,我真的不认为 ReactiveCocoa 或 PromiseKit 非常适合您的用例,因为您没有链接服务调用,而是 运行 并行调用它们。此外,您仍然需要 运行 所有解析逻辑并确定每个解析逻辑是成功还是失败,然后相应地更新您的应用程序。我要说的是,选项 2 将是迄今为止最好的选择,除非你想全力以赴将 PromiseKit 或 ReactiveCocoa 与 Alamofire 的响应序列化程序结合起来。
以下是我建议的让事情不那么复杂的方法。
import Foundation
import Alamofire
class ParallelServiceCaller {
var firstServiceCallComplete = false
var secondServiceCallComplete = false
func startServiceCalls() {
let firstRequest = Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["first": "request"])
firstRequest.responseString { request, response, dataString, error in
self.firstServiceCallComplete = true
self.handleServiceCallCompletion()
}
let secondRequest = Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["second": "request"])
secondRequest.responseString { request, response, dataString, error in
self.secondServiceCallComplete = true
self.handleServiceCallCompletion()
}
}
private func handleServiceCallCompletion() {
if self.firstServiceCallComplete && self.secondServiceCallComplete {
// Handle the fact that you're finished
}
}
}
实施非常简洁,易于遵循。虽然我理解你想要摆脱完成标志和回调函数的愿望,但其他选项,如 ReactiveCocoa and/or PromiseKit 仍然会有额外的逻辑,最终可能会使事情变得更复杂。
另一种可能的选择是使用调度组和信号量,但这确实增加了复杂性,但可以使您更接近 ReactiveCocoa 或 PromiseKit 风格的方法。
我希望这有助于阐明一些问题。
DispatchGroup
是并行处理多个依赖请求的好选择
func loadData() {
let dispatchGroup = DispatchGroup()
func startRequests() {
dispatchGroup.enter()
loadDataRequest1()
dispatchGroup.enter()
loadDataRequest2()
dispatchGroup.notify(queue: .main) { [weak self] in
// Process your responses
}
loadDataRequest1() {
// Save your response
dispatchGroup.leave()
}
loadDataRequest2() {
// Save your response
dispatchGroup.leave()
}
}
startRequests()
}