处理相互依赖的并发http请求
Deal with concurrent http requests that depend on each other
所以,我有一个复杂的数据要获取,它涉及 4 个请求,每个请求都取决于最后一个请求的结果,然后 returns 中的一些是一个列表,因此对于该列表中的每个元素,我必须得到一些信息。
上下文
我正在使用 YouTube API,我必须获取的数据是用户订阅的频道发送的最新视频列表。
这是执行此操作所需的请求:
获取/subscriptions/list[1]
获取/channels/list[2]
获取/playlistItems/list[3]
获取/视频[4]
[1]: Returns 用户订阅的频道列表。 return 大小配置为 5,因此我必须重复此请求,直到获取所有订阅的频道
[2]: Returns 特定频道已发送视频播放列表的 id
[3]: Returns n 个特定频道的最后一个视频
[4]:Returns 特定视频的信息
第一次尝试
一开始我是同步获取数据的,就是执行request[1],直到所有channel都取完。然后,我遍历频道列表,并为每个频道执行请求 [2] 以获取播放列表的 ID。然后请求 [3] 获取 n 个视频,对于每个视频,使用请求 [4] 获取其信息。
问题
问题是 return 向用户发送视频需要很长时间,所以我想到了并行执行请求。问题是我需要知道所有请求何时完成 运行,才能按日期重新排序视频列表。为此,我的代码到处都是 DispatchGroup 的复杂混乱。
所以,简而言之,处理这样的问题的最佳方法是什么,我有各种相互依赖的请求,我想并行执行其中的一些(第二个 - 我必须为每个通道执行)并且需要知道何时完成。
使用DispatchGroup
。 DispatchGroup是iOS中的一个"component",可以对一些相关操作进行分组,必须等待。
这里不能直接使用,为什么?因为 URLSession 本身将 web 操作发布在不同于发起者的后台线程上,所以我们必须手动 enter
和 leave
。当运算次数为0时,group.wait
returns.
此代码不是最佳设计模式。但这仅演示了在简单设计模式中可以完成的工作。
import UIKit
class URLRequestGroup {
var dispatchGroup: DispatchGroup
init(dispatchGroup: DispatchGroup) {
self.dispatchGroup = dispatchGroup
}
init() {
self.dispatchGroup = DispatchGroup()
}
func beginURLRequest(urlRequest: URLRequest,
completionHandler: @escaping (Data?, URLResponse?, Error?) -> ()) {
let urlSession = URLSession(configuration: URLSessionConfiguration.default)
// Enter the dispatchGroup manually
dispatchGroup.enter()
urlSession.dataTask(with: urlRequest, completionHandler: { [weak self] data, urlResponse, error in
completionHandler(data, urlResponse, error)
// Leave this dispatchGroup.
self?.dispatchGroup.leave()
}).resume()
}
}
let group = URLRequestGroup()
group.beginURLRequest(urlRequest: URLRequest(url: URL(fileURLWithPath: "http://www.example.com")), completionHandler: { data, urlResponse, error in
print(data?.count ?? 0)
})
// Put any other request here.
group.dispatchGroup.wait()
所以,我一直在努力尝试使用 NSURLSession
来组织这个复杂的请求过程,但我无法得到我想要的代码。
为了更容易使用,我使用了 Just,这使我能够以更简单、更清晰和容易的方式执行这些请求。
另一种选择是使用 PromiseKit, which easily allows chaining of requests.
将 NSURLSession
包装在承诺上
所以,我有一个复杂的数据要获取,它涉及 4 个请求,每个请求都取决于最后一个请求的结果,然后 returns 中的一些是一个列表,因此对于该列表中的每个元素,我必须得到一些信息。
上下文
我正在使用 YouTube API,我必须获取的数据是用户订阅的频道发送的最新视频列表。
这是执行此操作所需的请求:
获取/subscriptions/list[1]
获取/channels/list[2]
获取/playlistItems/list[3]
获取/视频[4]
[1]: Returns 用户订阅的频道列表。 return 大小配置为 5,因此我必须重复此请求,直到获取所有订阅的频道
[2]: Returns 特定频道已发送视频播放列表的 id
[3]: Returns n 个特定频道的最后一个视频
[4]:Returns 特定视频的信息
第一次尝试
一开始我是同步获取数据的,就是执行request[1],直到所有channel都取完。然后,我遍历频道列表,并为每个频道执行请求 [2] 以获取播放列表的 ID。然后请求 [3] 获取 n 个视频,对于每个视频,使用请求 [4] 获取其信息。
问题
问题是 return 向用户发送视频需要很长时间,所以我想到了并行执行请求。问题是我需要知道所有请求何时完成 运行,才能按日期重新排序视频列表。为此,我的代码到处都是 DispatchGroup 的复杂混乱。
所以,简而言之,处理这样的问题的最佳方法是什么,我有各种相互依赖的请求,我想并行执行其中的一些(第二个 - 我必须为每个通道执行)并且需要知道何时完成。
使用DispatchGroup
。 DispatchGroup是iOS中的一个"component",可以对一些相关操作进行分组,必须等待。
这里不能直接使用,为什么?因为 URLSession 本身将 web 操作发布在不同于发起者的后台线程上,所以我们必须手动 enter
和 leave
。当运算次数为0时,group.wait
returns.
此代码不是最佳设计模式。但这仅演示了在简单设计模式中可以完成的工作。
import UIKit
class URLRequestGroup {
var dispatchGroup: DispatchGroup
init(dispatchGroup: DispatchGroup) {
self.dispatchGroup = dispatchGroup
}
init() {
self.dispatchGroup = DispatchGroup()
}
func beginURLRequest(urlRequest: URLRequest,
completionHandler: @escaping (Data?, URLResponse?, Error?) -> ()) {
let urlSession = URLSession(configuration: URLSessionConfiguration.default)
// Enter the dispatchGroup manually
dispatchGroup.enter()
urlSession.dataTask(with: urlRequest, completionHandler: { [weak self] data, urlResponse, error in
completionHandler(data, urlResponse, error)
// Leave this dispatchGroup.
self?.dispatchGroup.leave()
}).resume()
}
}
let group = URLRequestGroup()
group.beginURLRequest(urlRequest: URLRequest(url: URL(fileURLWithPath: "http://www.example.com")), completionHandler: { data, urlResponse, error in
print(data?.count ?? 0)
})
// Put any other request here.
group.dispatchGroup.wait()
所以,我一直在努力尝试使用 NSURLSession
来组织这个复杂的请求过程,但我无法得到我想要的代码。
为了更容易使用,我使用了 Just,这使我能够以更简单、更清晰和容易的方式执行这些请求。
另一种选择是使用 PromiseKit, which easily allows chaining of requests.
将NSURLSession
包装在承诺上