等到多个请求被执行并且它们的完成块
Wait until multiple request to be executed and their completion block
考虑一个场景,我有一个函数"REFRESH",这个函数被不同的方法同时调用,假设这些方法是"A"、"B"、"C" .如果方法 "A" 首先调用 "REFRESH TOKEN",那么方法 "B" 和 "C" 应该等到它完成。
我怎样才能实现这种情况?感谢您的帮助!
let serialQueue = DispatchQueue(label: "serialQueue")
var myFlag = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.refresh(param: 1) // Method A
self.refresh(param: 2) // Method B
self.refresh(param: 3) // Method C
}
// Method REFRESH
func refresh(param: NSInteger) -> Void {
let absolutePath = "MY SAMPLE API"
var headers: [String: String] = Dictionary<String, String>();
headers["Content-Type"] = "application/json"
serialQueue.sync {
print("\nEntered ", param)
Alamofire.request(absolutePath, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers).responseString {
response in
switch response.result {
case .success:
print("SUCCESS")
break
case .failure(let error):
print(error)
}
}
以上代码输出:
Entered 1
Entered 2
Entered 3
SUCCESS
SUCCESS
SUCCESS
我需要这样的输出:
Entered 1
SUCCESS
Entered 2
SUCCESS
Entered 3
SUCCESS
func refresh(param: NSInteger, completion: (Void) -> ()) -> Void {
let absolutePath = "MY SAMPLE API"
var headers: [String: String] = Dictionary<String, String>();
headers["Content-Type"] = "application/json"
print("\nEntered ", param)
Alamofire.request(absolutePath, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers).responseString {
response in
switch response.result {
case .success:
completion()
break
case .failure(let error):
completion()
}
}
}
//In viewDidLoad :- Add these below code
// Create one custom queue.
let serialQueue = DispatchQueue(label: "serialQueue")
// Create one dispacth group.
let dispatchGorup = DispatchGroup()
//Call first refresh method with respective parameters.
dispatchGorup.enter()
//Wait for the response and then call leave method.
refresh(param: "") { (result) in
dispatchGorup.leave()
}
//Call second refresh method with respective parameters.
dispatchGorup.enter()
//Wait for the response and then call leave method.
refresh(param: "") { (result) in
dispatchGorup.leave()
}
//Indication that all the request is done.
dispatchGorup.notify(queue: serialQueue) {
Print("All methods invoked")
}
是这样的吗?
var param:[Int] = [1,2,3]
func refresh(){
DispatchQueue.global().async {
for i in 0..<param.count{
let group = DispatchGroup()
group.enter()
print("\nEntered ", param[i])
let absolutePath = "MY SAMPLE API"
var headers: [String: String] = Dictionary<String, String>();
headers["Content-Type"] = "application/json"
Alamofire.request(absolutePath, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers).responseString {
response in
switch response.result {
case .success:
print("SUCCESS")
break
case .failure(let error):
print(error)
}
group.leave()
}
group.wait()
}
}
}
根据您的要求,我会说您想要对这些 refresh
调用进行序列化调用。这意味着您必须等到一个呼叫结束才能呼叫下一个。
简单但有点难看的解决方案是使用完成闭包:
override func viewDidLoad() {
super.viewDidLoad()
self.refresh(param: 1, completion: { [weak self] in
self?.refresh(param: 2, completion: { [weak self] in
self?.refresh(param: 3, completion: nil)
})
})
}
// Method REFRESH
func refresh(param: NSInteger, completion: (() -> Void)?) -> Void {
let absolutePath = "MY SAMPLE API"
var headers: [String: String] = Dictionary<String, String>();
headers["Content-Type"] = "application/json"
print("\nEntered ", param)
Alamofire.request(absolutePath, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers).responseString {
response in
switch response.result {
case .success:
print("SUCCESS")
break
case .failure(let error):
print(error)
}
completion?()
}
}
根据您在评论中所说的内容(您只想从第一次调用中获取刷新令牌,然后没关系),您可以 viewDidLoad
将其重写为:
self.refresh(param: 1, completion: { [weak self] in
// these two can now go in parallel, since the first call got you the refresh token
self?.refresh(param: 2, completion: nil)
self?.refresh(param: 3, completion: nil)
})
你需要的是一个叫做资源锁定的东西。您可以使用 DispatchGroup
.
来实现此目的
首先您需要创建一个 DispatchGroup
。在您的控制器中添加一个 属性:
let dispatchGroup = DispatchGroup()
然后将您的 refresh(param:)
函数修改为:(我修改了一些编码模式)
func refresh(param: NSInteger) -> Void {
// You lock your resource by entering to the dispatch group
dispatchGroup.enter()
let absolutePath = "MY SAMPLE API"
var headers = [String: String]()
headers["Content-Type"] = "application/json"
print("Entered \(param)")
Alamofire.request(absolutePath, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers).responseString { [weak self] (response) in
switch response.result {
case .success:
print("SUCCESS \(param)")
break
case .failure(let error):
print(error)
}
// You release the resource as soon as you get the response so that other processes may be able to use the resource
self?.dispatchGroup.leave()
}
// The lock continues by invoking the wait method
dispatchGroup.wait()
}
因此,这将作为:
Method 1
& Method 2
正在请求使用相同的资源。当Method 1
执行时,Method 2
会等待方法1完成。 Method 1
完成后,Method 2
将有机会开始执行。
所以,基本上哪个方法先开始执行就会执行完,然后另一个就会开始。虽然不能保证哪个会先开始执行(因为,你们不需要相互依赖)。但这将取决于您调用此方法的顺序。
考虑一个场景,我有一个函数"REFRESH",这个函数被不同的方法同时调用,假设这些方法是"A"、"B"、"C" .如果方法 "A" 首先调用 "REFRESH TOKEN",那么方法 "B" 和 "C" 应该等到它完成。
我怎样才能实现这种情况?感谢您的帮助!
let serialQueue = DispatchQueue(label: "serialQueue")
var myFlag = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.refresh(param: 1) // Method A
self.refresh(param: 2) // Method B
self.refresh(param: 3) // Method C
}
// Method REFRESH
func refresh(param: NSInteger) -> Void {
let absolutePath = "MY SAMPLE API"
var headers: [String: String] = Dictionary<String, String>();
headers["Content-Type"] = "application/json"
serialQueue.sync {
print("\nEntered ", param)
Alamofire.request(absolutePath, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers).responseString {
response in
switch response.result {
case .success:
print("SUCCESS")
break
case .failure(let error):
print(error)
}
}
以上代码输出:
Entered 1
Entered 2
Entered 3
SUCCESS
SUCCESS
SUCCESS
我需要这样的输出:
Entered 1
SUCCESS
Entered 2
SUCCESS
Entered 3
SUCCESS
func refresh(param: NSInteger, completion: (Void) -> ()) -> Void {
let absolutePath = "MY SAMPLE API"
var headers: [String: String] = Dictionary<String, String>();
headers["Content-Type"] = "application/json"
print("\nEntered ", param)
Alamofire.request(absolutePath, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers).responseString {
response in
switch response.result {
case .success:
completion()
break
case .failure(let error):
completion()
}
}
}
//In viewDidLoad :- Add these below code
// Create one custom queue.
let serialQueue = DispatchQueue(label: "serialQueue")
// Create one dispacth group.
let dispatchGorup = DispatchGroup()
//Call first refresh method with respective parameters.
dispatchGorup.enter()
//Wait for the response and then call leave method.
refresh(param: "") { (result) in
dispatchGorup.leave()
}
//Call second refresh method with respective parameters.
dispatchGorup.enter()
//Wait for the response and then call leave method.
refresh(param: "") { (result) in
dispatchGorup.leave()
}
//Indication that all the request is done.
dispatchGorup.notify(queue: serialQueue) {
Print("All methods invoked")
}
是这样的吗?
var param:[Int] = [1,2,3]
func refresh(){
DispatchQueue.global().async {
for i in 0..<param.count{
let group = DispatchGroup()
group.enter()
print("\nEntered ", param[i])
let absolutePath = "MY SAMPLE API"
var headers: [String: String] = Dictionary<String, String>();
headers["Content-Type"] = "application/json"
Alamofire.request(absolutePath, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers).responseString {
response in
switch response.result {
case .success:
print("SUCCESS")
break
case .failure(let error):
print(error)
}
group.leave()
}
group.wait()
}
}
}
根据您的要求,我会说您想要对这些 refresh
调用进行序列化调用。这意味着您必须等到一个呼叫结束才能呼叫下一个。
简单但有点难看的解决方案是使用完成闭包:
override func viewDidLoad() {
super.viewDidLoad()
self.refresh(param: 1, completion: { [weak self] in
self?.refresh(param: 2, completion: { [weak self] in
self?.refresh(param: 3, completion: nil)
})
})
}
// Method REFRESH
func refresh(param: NSInteger, completion: (() -> Void)?) -> Void {
let absolutePath = "MY SAMPLE API"
var headers: [String: String] = Dictionary<String, String>();
headers["Content-Type"] = "application/json"
print("\nEntered ", param)
Alamofire.request(absolutePath, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers).responseString {
response in
switch response.result {
case .success:
print("SUCCESS")
break
case .failure(let error):
print(error)
}
completion?()
}
}
根据您在评论中所说的内容(您只想从第一次调用中获取刷新令牌,然后没关系),您可以 viewDidLoad
将其重写为:
self.refresh(param: 1, completion: { [weak self] in
// these two can now go in parallel, since the first call got you the refresh token
self?.refresh(param: 2, completion: nil)
self?.refresh(param: 3, completion: nil)
})
你需要的是一个叫做资源锁定的东西。您可以使用 DispatchGroup
.
首先您需要创建一个 DispatchGroup
。在您的控制器中添加一个 属性:
let dispatchGroup = DispatchGroup()
然后将您的 refresh(param:)
函数修改为:(我修改了一些编码模式)
func refresh(param: NSInteger) -> Void {
// You lock your resource by entering to the dispatch group
dispatchGroup.enter()
let absolutePath = "MY SAMPLE API"
var headers = [String: String]()
headers["Content-Type"] = "application/json"
print("Entered \(param)")
Alamofire.request(absolutePath, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers).responseString { [weak self] (response) in
switch response.result {
case .success:
print("SUCCESS \(param)")
break
case .failure(let error):
print(error)
}
// You release the resource as soon as you get the response so that other processes may be able to use the resource
self?.dispatchGroup.leave()
}
// The lock continues by invoking the wait method
dispatchGroup.wait()
}
因此,这将作为:
Method 1
& Method 2
正在请求使用相同的资源。当Method 1
执行时,Method 2
会等待方法1完成。 Method 1
完成后,Method 2
将有机会开始执行。
所以,基本上哪个方法先开始执行就会执行完,然后另一个就会开始。虽然不能保证哪个会先开始执行(因为,你们不需要相互依赖)。但这将取决于您调用此方法的顺序。