如何执行一个接一个完成的多个 Alamofire 请求?
How is it possible to perform multiple Alamofire requests that are finished one after another?
我想执行多个 Alamofire 请求。但是,由于数据依赖性,新请求只能在前一个请求完成后才开始。
我已经用 OperationQueue
解决了一个更通用的异步请求示例来询问 。但是,我没有成功地使用 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
}
}
为了确保请求在下一个请求开始之前完成,我使用 OperationQueue
如下:
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)
}
然而,输出是:
Operation #0 finished
Operation #3 finished
Operation #2 finished
Operation #1 finished
这显然是不正确的。
如何使用 Alamofire 实现这一目标?
问题与您提出的 中的问题相同:操作依赖于完成操作,如记录的那样,但是您编写了代码,在异步调度未来的请求后操作退出执行(您创建并添加到队列的操作将按照其依赖项设置的顺序完成,但请求将由 Alamofire 底层的 NSURLSession 同时触发)。
如果您需要串行执行,您可以执行以下操作:
// 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)
}
讨论了各种其他解决方案, arguably a duplicate. There's also Alamofire-Synchronous。
我想执行多个 Alamofire 请求。但是,由于数据依赖性,新请求只能在前一个请求完成后才开始。
我已经用 OperationQueue
解决了一个更通用的异步请求示例来询问
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
}
}
为了确保请求在下一个请求开始之前完成,我使用 OperationQueue
如下:
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)
}
然而,输出是:
Operation #0 finished
Operation #3 finished
Operation #2 finished
Operation #1 finished
这显然是不正确的。
如何使用 Alamofire 实现这一目标?
问题与您提出的
如果您需要串行执行,您可以执行以下操作:
// 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)
}
讨论了各种其他解决方案