How is it possible to perform multiple Alamofire requests that are finished one after another?

故事扮演 提交于 2019-12-02 17:33:35

问题


I would like to perform multiple Alamofire requests. However, because of data dependency a new request should only start when the previous is finished.

I already asked a question with a more general example of an asynchronous request which was solved with OperationQueue. However, I do not succeed to achieve the same with Alamofire.

public func performAlamofireRequest(_ number: Int, success: @escaping (Int) -> Void)->Void {
    Alamofire.request(String(format: "http://jsonplaceholder.typicode.com/posts/%i", number+1)) // NSURLSession dispatch queue
        .responseString { response in // Completion handler at main dispatch queue? 
            if response.result.isSuccess {
             //   print("data")
            } else if response.result.isFailure {
             //   print("error")
            }
            success(number) // Always leave closure in this example
    }
}

To assure that requests are finished before a next request is started, I use OperationQueue as follows:

let operationQueue = OperationQueue.main
for operationNumber in 0..<4 { // Create some operations
    let operation = BlockOperation(block: {
        performAlamofireRequest(operationNumber) { number in
            print("Operation #\(number) finished")
    }
})
operation.name = "Operation #\(operationNumber)"

    if operationNumber > 0 {
        operation.addDependency(operationQueue.operations.last!)
    }
    operationQueue.addOperation(operation)
}

However, the output is:

Operation #0 finished
Operation #3 finished
Operation #2 finished
Operation #1 finished

which is clearly not correct.

How would it be possible to achieve this with Alamofire?


回答1:


The issue is just the same as in the related question you posed: the operation dependencies are on finishing an operation, as documented, but you have written code where the operation exits after asynchronously dispatching a request for future execution (the operations you created and added to a queue will finish in the order set by their dependencies, but the requests will be fired concurrently by the NSURLSession underlying Alamofire).

If you need serial execution, you can for instance do the following:

// you should create an operation queue, not use OperationQueue.main here –
// synchronous network IO that would end up waiting on main queue is a real bad idea.
let operationQueue = OperationQueue()
let timeout:TimeInterval = 30.0

for operationNumber in 0..<4 {
    let operation = BlockOperation {
        let s = DispatchSemaphore(value: 0)
        self.performAlamofireRequest(operationNumber) { number in
            // do stuff with the response.
            s.signal()
        }

        // the timeout here is really an extra safety measure – the request itself should time out and end up firing the completion handler.
        s.wait(timeout: DispatchTime(DispatchTime.now, Int64(timeout * Double(NSEC_PER_SEC))))
    }

    operationQueue.addOperation(operation)
}

Various other solutions are discussed in connection to this question, arguably a duplicate. There's also Alamofire-Synchronous.



来源:https://stackoverflow.com/questions/39919852/how-is-it-possible-to-perform-multiple-alamofire-requests-that-are-finished-one

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!