11

How can I make a synchronous operation with asynchronous function?

class MyClass {
    static let shared = MyClass()
    let operationQueue = OperationQueue()
    let dispatchGroup  = DispatchGroup()

    func request(_ myRequestURL: URL) {
        operationQueue.addOperation {
            self.dispatchGroup.enter()
            // Async function
            Alamofire.request(myRequestURL).response { response in
                print(response.request)
                self.dispatchGroup.leave()
            }

            self.dispatchGroup.wait(timeout: .distantFuture)
        }
    }
}

MyClass.shared.request(A)
MyClass.shared.request(B)
MyClass.shared.request(C)

output: C > A > B
expected: A > B > C


I know there is a completion block method to do so. But the requests will be nested.

func request(_ myRequestURL: URL, completion: @escaping (_ data: Data?) -> Void) {
    // Async function
    Alamofire.request(myRequestURL).response { response in
        completion(response.data)
    }
}

MyClass.shared.request(A) { _ in
     MyClass.shared.request(B) { _ in
         MyClass.shared.request(C) { _ in
        }
    }
}

Willjay
  • 6,381
  • 4
  • 33
  • 58
  • Possible duplicate of [Chain multiple Alamofire requests](http://stackoverflow.com/questions/28634995/chain-multiple-alamofire-requests) – kennytm Apr 13 '17 at 09:44
  • 1
    Make your queue serial: `operationQueue.maxConcurrentOperationCount = 1` – shallowThought Apr 13 '17 at 10:02
  • Yep. It' like [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) in javascript. How can I do in Swifty way with GCD? – Willjay Apr 14 '17 at 01:40
  • Do the requests depend on each other or can they execute concurrently? In the former case, you end up "nesting" them where the next request possibly requires the result of the previous request. This also implies that the async tasks are performed sequentially. Otherwise, if the requests are independent, run them concurrently and proceed when all have been completed. The approach that you need depends on this decision. – CouchDeveloper Apr 14 '17 at 09:11

1 Answers1

22

It works for me using DispatchQueue instead.

class MyClass {
    static let shared = MyClass()
    let dispatchQueue = DispatchQueue(label: "ALAMOFIRE_REQUEST")
    let dispatchGroup  = DispatchGroup()

    func request(_ myRequestURL: URL) {
        dispatchQueue.async {
            self.dispatchGroup.enter()
            // Async function
            Alamofire.request(myRequestURL).response { response in
                print(response.request)
                self.dispatchGroup.leave()
            }

            self.dispatchGroup.wait(timeout: .distantFuture)
        }
    }
}
Willjay
  • 6,381
  • 4
  • 33
  • 58