等到多个请求被执行并且它们的完成块

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 将有机会开始执行。

所以,基本上哪个方法先开始执行就会执行完,然后另一个就会开始。虽然不能保证哪个会先开始执行(因为,你们不需要相互依赖)。但这将取决于您调用此方法的顺序。