【问题标题】:Handle timeout with Alamofire使用 Alamofire 处理超时
【发布时间】:2016-08-06 04:23:10
【问题描述】:

是否可以为 Alamofire 请求添加超时处理程序?

在我的项目中,我以这种方式使用 Alamofire:

init() {
    let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
    configuration.timeoutIntervalForRequest = 30

    self.alamofireManager = Alamofire.Manager(configuration: configuration)
}

func requestAuthorizationWithEmail(email:NSString, password:NSString, completion: (result: RequestResult) -> Void) {

    self.alamofireManager!.request(.POST, "myURL", parameters:["email": email, "password":password])
        .responseJSON { response in
            switch response.result {
            case .Success(let JSON):
                //do json stuff
            case .Failure(let error):
                print("\n\nAuth request failed with error:\n \(error)")
                completion(result: .ConnectionFailed)
            }
    }
}

编辑:

请求失败消息

Error Domain=NSURLErrorDomain Code=-1001 "请求超时。" UserInfo={NSUnderlyingError=0x7fc10b937320 {错误域=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=url, NSErrorFailingURLKey=url, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102 , NSLocalizedDescription=请求超时。}

【问题讨论】:

  • 超时不也触发.Failure吗?从未使用 Alamofire 对其进行过测试,但我使用的大多数其他系统都会回退到类似的错误/故障。你测试了什么?
  • @Allendar 你是对的,我的错,我没有提到这一点。我已经编辑了我的问题。
  • 响应对象将包含 HTTP 状态。如果是 408(408 请求超时),那么您可以在 .Failure 调用中检查它并适当地处理它。甚至可能还有用于 http 状态的宏,因此您可以简单地将 HTTP_STATUS_408 之类的内容作为整数占位符进行检查。

标签: swift alamofire


【解决方案1】:

您可以比较error._code,如果它等于-1001,即NSURLErrorTimedOut,那么您就知道这是一个超时。

let manager = Alamofire.SessionManager.default
manager.session.configuration.timeoutIntervalForRequest = 120

manager.request("yourUrl", method: .post, parameters: ["parameterKey": "value"])
        .responseJSON {
            response in
            switch (response.result) {
            case .success: // succes path 
            case .failure(let error):
                if error._code == NSURLErrorTimedOut {
                    print("Request timeout!")
                }
            }
        }

【讨论】:

  • 这是真的,但没有被提倡这样做,因为如果你在团队中工作,这些对精确“水下”代码的奇怪检查将使代码非常不可读。尽管如此,这是一个正确的答案,所以+1。
  • 完全同意你的看法,我做了一些更新,让这个 sn-p 更易于阅读:)
  • 我做了一些研究,我们可以使用NSURLError类中的NSURLErrorTimedOut
  • 我使用这个 sn-p 来处理超时错误。我的平台是 Xcode 8,Swift 3。枚举结果值似乎是 .success.failure 而不是 .Success.Failure
  • 谁能告诉我怎么知道使用error._code?这似乎没有出现在任何文档中
【解决方案2】:

斯威夫特 3

接受的答案对我不起作用。

经过大量研究,我是这样做的:

let manager = Alamofire.SessionManager.default
manager.session.configuration.timeoutIntervalForRequest = 120

manager.request("yourUrl", method: .post, parameters: ["parameterKey": "value"])

【讨论】:

    【解决方案3】:

    Swift 3,Alamofire 4.5.0

    我想为我项目中的每个 HTTP 调用设置相同的超时

    关键思想是将 Alamofire 会话管理器 声明为全局变量。然后创建一个 URLSessionConfiguration 变量,以秒为单位设置其超时并将其分配给管理器。

    项目中的每个调用都可以使用这个配置的会话管理器

    在我的例子中,全局 Alamofire Session Manager 变量是在 AppDelegate 文件中设置的(全局),并且它的配置在其 didFinishLaunchingWithOptions 方法中进行管理

    AppDelegate.swift

    import UIKit
    
    var AFManager = SessionManager()
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
    
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    
            let configuration = URLSessionConfiguration.default
            configuration.timeoutIntervalForRequest = 4 // seconds
            configuration.timeoutIntervalForResource = 4 //seconds
            AFManager = Alamofire.SessionManager(configuration: configuration)
    
            return true
        }
        ...
    }
    

    从现在开始,可以使用 afManager 从应用程序的任何部分调用 Alamofire 请求 函数。

    例如:

    AFManager.request("yourURL", method: .post, parameters: parameters, encoding: JSONEncoding.default).validate().responseJSON { response in
        ...
    }
    

    【讨论】:

    • 你能提供最新版本的alamofire代码吗?传统知识
    • 救了我的命(Y)
    【解决方案4】:

    Swift 3.x

    class NetworkHelper {
        static let shared = NetworkHelper()
        var manager: SessionManager {
            let manager = Alamofire.SessionManager.default
            manager.session.configuration.timeoutIntervalForRequest = 10
            return manager
        }
        func postJSONData( withParams parameters: Dictionary<String, Any>, toUrl urlString: String, completion: @escaping (_ error: Error,_ responseBody: Dictionary<String, AnyObject>?)->()) {
            manager.request(urlString, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseJSON { response in 
                if let error = response.result.error {
                    if error._code == NSURLErrorTimedOut {
                        print("Time out occurs!")
                    }
                }
            }
        }
    }
    

    【讨论】:

      【解决方案5】:

      Swift 5、Alamofire 5

      我发现的最干净的方式,适用于最新版本的 Alamofire 如下:

      AF.request(url).response { (dataResponse: AFDataResponse<Data?>) in
          switch dataResponse.result {
          case .success(let data):
              // succes path
          case .failure(let error):
              switch error {
              case .sessionTaskFailed(URLError.timedOut):
                  print("Request timeout!")
              default:
                  print("Other error!")
              }
          }
      }
      

      【讨论】:

        【解决方案6】:

        Swift 3.x

        接受的答案对我也不起作用。

        这对我有用!

        let url = URL(string: "yourStringUrl")!
        var urlRequest = URLRequest(url: url)
        urlRequest.timeoutInterval = 5 // or what you want
        

        之后:

        Alamofire.request(urlRequest).response(completionHandler: { (response) in
            /// code here
        }
        

        【讨论】:

          【解决方案7】:

          斯威夫特 4

          我的方式和超时功能是可行的,同时为api类练习单例。 来自here的参考

          struct AlamofireManager {
              static let shared: SessionManager = {
                  let configuration = URLSessionConfiguration.default
                  configuration.timeoutIntervalForRequest = 5
                  let sessionManager = Alamofire.SessionManager(configuration: configuration, delegate: SessionDelegate(), serverTrustPolicyManager: nil)
                  return sessionManager
              }()
          }
          
          class Auth {
              static let api = Auth()
          
              private init() {}
          
              func headers() -> HTTPHeaders {
                  return [
                      "Accept": "XXX",
                      "Authorization": "XXX",
                      "Content-Type": "XXX"
                  ]
              }
          
              func querySample() {
          
                  AlamofireManager.shared.request("api_post_url", method: .post, parameters: ["parametersKey": "value"], encoding: JSONEncoding.default, headers: headers())
                      .responseJSON(queue: DispatchQueue.global(), options: []) { (response) in
                      switch response.result {
                      case .success(let value):
                          // do your statement
                      case .failure(let error):
                          if error._code == NSURLErrorTimedOut {
                              // timeout error statement
                          } else {
                              // other error statement
                          }
                      }
                  })
              }
          
              func queryOtherSample() {
          
                  AlamofireManager.shared.request("api_get_url", method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers())
                      .responseJSON(queue: DispatchQueue.global(), options: []) { (response) in
                      switch response.result {
                      case .success(let value):
                          // do your statement
                      case .failure(let error):
                          if error._code == NSURLErrorTimedOut {
                              // timeout error statement
                          } else {
                              // other error statement
                          }
                      }
                  })
              }
          
          }
          

          【讨论】:

          • 这会抛出Error Domain=NSURLErrorDomain Code=-999 "cancelled"
          • @brahimm 请尝试改进线程队列,使用 DispatchQueue.global() 作为我的更新
          • 你能告诉我为什么指定后台线程可以解决这个问题!
          • 我认为这个错误是由于多个请求同时查询串行队列。将 DispatchQueue.global() 改进为并发队列。
          • 问题依旧
          【解决方案8】:

          对于 Swift 3.x / Swift 4.0 / Swift 5.0 用户使用 Alamofire >= 5.0

          使用请求修饰符来增加和减少超时间隔。

          Alamofire 的 请求创建方法提供了最常用的自定义参数,但有时这些参数还不够。从传递的值创建的 URLRequests 可以在创建请求时使用 RequestModifier 闭包进行修改。例如,要将 URLRequest 的 timeoutInterval 设置为 120 秒,请在闭包中修改请求。

          var manager = Session.default
           manager.request(urlString, method: method, parameters: dict, headers: headers, requestModifier: { $0.timeoutInterval = 120 }).validate().responseJSON { response in
          

          RequestModifiers 也适用于尾随闭包语法。

          var manager = Session.default
               manager.request("https://httpbin.org/get") { urlRequest in
              urlRequest.timeoutInterval = 60
              urlRequest.allowsConstrainedNetworkAccess = false
          }
          .response(...)
          

          您也可以查看here

          【讨论】:

            【解决方案9】:

            扩展 SessionManager 并像这样编写一个公共静态变量, “requestTimeOutInterval”这是一个公共变量。它有时间。

            extension SessionManager {
                public static let custom: SessionManager = {
                    let configuration = URLSessionConfiguration.default
                    configuration.timeoutIntervalForRequest = requestTimeOutInterval
                    configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
            
                    return SessionManager(configuration: configuration)
                }()
            }
            

            【讨论】:

              【解决方案10】:

              Swift 5.0,Alamofire 5.4.2

              超时时的错误码总是等于NSURLErrorTimedOut,所以 我尝试从 AFError 中检索 Error 对象并向上转换为 NSError。

              extension AFError {
                  var isTimeout: Bool {
                      if isSessionTaskError,
                         let error = underlyingError as NSError?,
                         error.code == NSURLErrorTimedOut //-1001
                      {
                          return true
                      }
                      return false
                  }
              }
              

              在响应关闭时调用。

              let request = URLRequest(url: URL(string: "https://httpbin.org/delay/10")!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 2)
              AF.request(request).responseString(completionHandler: { response in
                  switch response.result {
                  case .success(_):
                      print("success")
                  case .failure(let error):
                      if error.isTimeout {
                          print("Timeout!")
                      }
                  }
              })
              

              【讨论】:

                猜你喜欢
                • 2021-10-05
                • 2017-06-01
                • 1970-01-01
                • 2016-09-08
                • 1970-01-01
                • 2014-12-27
                • 2021-07-02
                • 1970-01-01
                相关资源
                最近更新 更多