2016-05-24 39 views
8

我有很多Alamofire请求/响应代码处理的地方。有没有办法做Alamofire请求重试

由于某些间歇性问题(最常见的是片状网络),每个请求可能会失败。

我希望能够在救援之前重试请求3次。

直截了当的方法是有类似的东西

var errorCount = 0 
func requestType1() { 
    let request = Alamofire.request(...).responseJSON { response in 
     if (isError(response) && errorCount < 3) { 
      errorCount += 1 
      request1() 
     } 
     if (isError(response)) { 
      handleError() 
     } 

     handleSuccess() 
    } 
} 

不过,我不喜欢这种方法的多种原因很多。最明显的是,我需要为每个请求类型实现这样的代码(我有类似的15个)。

我珍玩是否有办法做到像(其中的变化是最小的,非侵入式)

let request = Alamofire.request(..., **3**) 
+0

你可以做一个包装,接受请求一结束块?那么,不是直接调用请求,而是在块中有相同的请求代码,但调用封装器?更易于更改代码。 – Carlos

+0

卡洛斯。我想你是对的。我忽略了这个:)。你想写作答案? –

+0

当然,给我一点时间,我会这样做 – Carlos

回答

3

One一同斯威夫特得到的是你可以使用这个语法糖位:

public func updateEvents(someNormalParam: Bool = true, someBlock: (Void->Void)) 

像这样:

updateEvents(someNormalParam: false) {...} 

注意该块是外upda的() teEvents功能,与您通常所期望的相反。它只有在块是功能声明中的最后一项时才起作用。

这意味着,如果你碰巧有一个块,如您Alamofire的要求,就可以有效地与重试功能的包裹。一个稍微复杂的问题是你想调用块内的块。没什么大不了的:

func retryWrapper(alamoBlock: (Void->Request)) { 
    alamoblock().responseJSON() { 
     //Your retry logic here 
    } 
} 

你使用它,像这样:

retryWrapper() { 
    Alamofire.request(method, targetUrl, parameters: parameters, encoding: encoding) 
} 

意味着所有你需要做的就是找到你的Alamofire调用和{}将它们包装和()之前把retryWrapper。重试逻辑本身只有一次。

+0

我有点困惑在这里..我们responseJSON()在这里? – Ranjit

+0

我有点生疏,但它看起来像块返回一个请求,其中有一个函数,将它变成JSON – Carlos

+0

不能我们使用requestRetrier? – Ranjit

-3

那么我所做的是下面的,如果请求失败,我发出一个失败的通知谁提出的要求。然后它负责重试请求。发现这很容易。

Alamofire.request(.GET, urlString, parameters: params, headers: defaultHeaders) 
     .validate() 
     .responseJSON 
     { 
      response in 

      switch response.result 
      { 
      case .Success: 
       print("Request Successful") 

       let json = JSON(data:response.data!) 

       NSNotificationCenter.defaultCenter().postNotificationName(SUCCESS_NOTIFICATION, object: movieArray) 

      case .Failure(let error): 
       print("Request Failed with error \(error)") 
       NSNotificationCenter.defaultCenter().postNotificationName(FAILURE_NOTIFICATION, object: error) 
      } 
    } 
+2

我不推荐这种方法。在使用NSNotifications时明智的做法是明智的。如果你正在使用它们,问问你自己是否没有更好的方法。 例如,在这种情况下,使用闭包进行回调将会好得多。使用闭包作为完成处理程序是这种事情的标准实践和模式。 –

10

Alamofire 4.0有一个RequestRetrier协议就可以使用。

https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%204.0%20Migration%20Guide.md#request-retrier

例子:

class OAuth2Handler: RequestAdapter, RequestRetrier { 
    public func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: RequestRetryCompletion) { 
     if let response = request.task.response as? HTTPURLResponse, response.statusCode == 401 { 
      completion(true, 1.0) // retry after 1 second 
     } else { 
      completion(false, 0.0) // don't retry 
     } 
    } 
} 

let sessionManager = SessionManager() 
sessionManager.retrier = OAuth2Handler() 

sessionManager.request(urlString).responseJSON { response in 
    debugPrint(response) 
} 
1

我有同样的问题,得到了请求使用RequestRetrier,should方法和request.retryCount重审。类似的东西: ` // MARK: - RequestRetry

public func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) { 
    lock.lock() ; defer { lock.unlock() } 


    if let response = request.task?.response as? HTTPURLResponse{ 
     if response.statusCode == 401 { 
      requestsToRetry.append(completion) 

      getToken { (expires, _) in 
       _ = SessionCountdownToken.sharedInstance.startCount(expirationTime: expires) 
      } 
     } else { 

      if request.retryCount == 3 { completion(false, 0.0); return} 
      completion(true, 1.0) 
      return 
     } 
    } else { 
     completion(false, 0.0) 
    } 
}` 
相关问题