2016-05-24 60 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) 
    } 
}` 
相關問題