Alamofire 串行请求

Posted

技术标签:

【中文标题】Alamofire 串行请求【英文标题】:Alamofire Serial Requests 【发布时间】:2016-01-21 21:08:26 【问题描述】:

我需要按顺序执行请求,尽管这在使用 Alamofire 时不起作用。

我想按顺序打印1到30(假设响应只是参数的回显)

// Only 1 connection per Host

let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPMaximumConnectionsPerHost =  1
configuration.timeoutIntervalForRequest = 30
self.manager = Alamofire.Manager(configuration: configuration) 

for i in 1...30 
    manager.request(.GET, "http://httpbin.org/get", "i" : i], encoding: .JSON)
        .responseJSON  response in
            switch (response.result)
            case .Failure(let error):
                print("error")
                break;
            case .Success(let json):
                print(json)
            
     )

【问题讨论】:

你陈述了你的期望,但没有陈述你的结果。如果您没有看到 1...30,您看到了什么,您认为这意味着什么是错误的? @Jonah,我看到了数字 1 到 30,但没有排序 【参考方案1】:

根据NSURLSessionConfiguration 的文档:

此属性确定基于此配置的会话中的任务与每个主机建立的最大同时连接数。

此限制针对每个会话,因此如果您使用多个会话,您的应用作为一个整体可能会超过此限制。此外,根据您与 Internet 的连接,会话使用的限制可能低于您指定的限制。

在 OS X 中默认值为 6,在 ios 中为 4。

如您所见,此设置仅控制网络级别的连接数。一旦您使用 NSURLSession(Alamofire 的基础)对多个请求进行排队,则由该类来确定您的请求何时发出。使用NSURLSession 或 Alamofire 无法保证在不以这种方式显式编码请求的情况下发出请求的顺序。

也就是说,通过将请求包装在 NSOperations 中,您可能可以获得您想要的行为。如果您使用.maxConcurrentOperationCount1 创建一个NSOperationQueue,您实际上创建了一个串行队列。然后使用您已经编写的相同循环,您应该能够像这样包装您的 Alamofire 请求:

queue.addOperationWithBlock 
    manager.request(.GET, "http://httpbin.org/get", "i" : i], encoding: .JSON)
        .responseJSON  response in
            switch (response.result)
            case .Failure(let error):
                print("error")
                break;
            case .Success(let json):
                print(json)
            
     )

 

使用.maxConcurrentOperationCount1,队列应该按顺序运行,正如我所提到的。因此,根据NSOperationQueue 的文档,您的操作将按照它们添加到队列中的顺序执行。所以你应该看到你想要的 1 到 30 的结果。

综上所述,对于您想要解决的问题,可能有更好的解决方案,除非这仅仅是为了按顺序获得这些结果的编码练习。

【讨论】:

谢谢!是的,我很困惑为什么请求没有按顺序执行。 这不对 manager.request 是异步的并立即返回,像这样包装它实际上没有任何作用 只要你把maxConcurrentOperationCount设置为1就可以了。【参考方案2】:

如Alamofire's Github page所述:

Alamofire 中的网络是异步完成的。异步编程可能会让不熟悉这个概念的程序员感到沮丧,但有 very good reasons 这样做。

因此,就使用 Alamofire 的本质而言,您将获得异步网络调用。您可以选择不同的库或使用基本 SDK 实现,但正如 Alamofire 的 Github 页面的 Apple 文档链接中所述,您会发现几乎每个网络库都是异步的,这是有原因的。

因此,为了方便您了解,Alamofire 的接口会同步接收您的调用,但除此之外,无法保证响应将以什么顺序返回给您。他们可能会以不同的顺序发出请求他们几乎肯定会以不同的顺序返回响应。

这里更好的选择是存储一个可变的响应数组,一旦它存储了您所做的每个网络调用的响应,就对数组进行排序,然后进行打印。

【讨论】:

是的,我知道 Alamofire 是异步的,并且具有异步编程的所有优点。应用程序的所有其他请求都是这种方式。事实上,我已经找到了解决我的问题的方法。真正的问题是:“为什么HTTPMaximumConnectionsPerHost = 1”没有按预期工作?或者HTTPMaximumConnectionsPerHost属性的真正含义是什么?对不起,如果问题不是很清楚【参考方案3】:

Alamofire 5:


import UIKit
import Alamofire

class ViewController: UIViewController 

    var session: Session?
    var opQueue: OperationQueue?
    var semaphore: DispatchSemaphore?
    
    override func viewDidLoad() 
        super.viewDidLoad()

        synchronous()
    

    
    func synchronous() 
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForRequest = 30
        
        self.session = Session(configuration: configuration)
        self.opQueue = OperationQueue()
        self.opQueue?.maxConcurrentOperationCount = 1
        self.semaphore = DispatchSemaphore(value: 0)

        for i in 1...30 
            self.opQueue?.addOperation  [weak self] in
                self?.session?.request("https://httpbin.org/get", method: .get, parameters: ["i" : i]).responseJSON(completionHandler:  response  in
                        switch (response.result)
                        case .failure(let error):
                            print("error: \(error)")
                            break;
                        case .success(let json):
                            if let json = json as? Dictionary<String, Any>, let data = json["args"] as? Dictionary<String, Any> 
                                print(data)
                            
                            
                        
                    self?.semaphore?.signal()
                 )
                
                self?.semaphore?.wait()
            
            
        
    



日志:

["i": 1]
["i": 2]
["i": 3]
["i": 4]
["i": 5]
["i": 6]
["i": 7]
["i": 8]
["i": 9]
["i": 10]
["i": 11]
["i": 12]
["i": 13]
["i": 14]
["i": 15]
["i": 16]
["i": 17]
["i": 18]
["i": 19]
["i": 20]
["i": 21]
["i": 22]
["i": 23]
["i": 24]
["i": 25]
["i": 26]
["i": 27]
["i": 28]
["i": 29]
["i": 30]

【讨论】:

以上是关于Alamofire 串行请求的主要内容,如果未能解决你的问题,请参考以下文章

使用 alamofire 的顺序上传/串行队列

Alamofire 4 请求打开天气

var 请求:Alamofire.Request?使用未声明类型的 Alamofire

邮递员请求 Alamofire 请求

Alamofire 请求为零

Alamofire 请求响应?