【问题标题】:How is it possible to perform multiple Alamofire requests that are finished one after another?如何执行多个一个接一个完成的 Alamofire 请求?
【发布时间】:2017-02-16 14:34:13
【问题描述】:

我想执行多个 Alamofire 请求。但是,由于数据依赖性,新请求仅应在前一个请求完成时开始。

我已经向question 询问了一个更一般的异步请求示例,该示例已通过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 实现这一目标?

【问题讨论】:

    标签: swift alamofire nsoperationqueue


    【解决方案1】:

    问题与您提出的related question 中的问题相同:操作依赖于完成操作,如文档所述,但是您编写了代码,在异步调度未来执行请求后操作退出(操作您创建并添加到队列将按照其依赖项设置的顺序完成,但请求将由底层 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)
    }
    

    讨论了各种其他解决方案in connection to this question,可以说是重复的。还有Alamofire-Synchronous

    【讨论】:

    • 这行得通,又是一个清晰的解释!我也同意操作队列不应该使用主队列。但是,如果无论如何都使用OperationQueue.main,我会期待一个 UI 块,但似乎根本没有调用 Alamofire 的完成处理程序(因此信号量没有发出信号)。虽然我不会以这种方式实现它,但我希望能理解它为什么不起作用……
    • 如果您使用OperationQueue.main 执行上面的块操作,则不会触发回调的原因,信号量wait 调用是在块操作内部进行的,并将阻塞主队列。如果超时不存在,在这种情况下,这将导致死锁。这种基于信号量的路由还可能存在另一个丑陋的微妙错误:如果在上述情况下的超时时间短于执行请求的 NSURLSession / NSURLRequest 的超时时间,则块操作完成,然后稍后会触发回调。我尽可能远离信号量:)
    猜你喜欢
    • 1970-01-01
    • 2016-12-02
    • 2017-02-13
    • 2016-05-28
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-22
    相关资源
    最近更新 更多